user image

Joseph Morgan
Published in : 2021-07-03

How to use SetFieldValue from outside render function? Formik

React js

SetFieldValue from outside the form? Formik js

How can i use SetFieldValue() from outside the main function (render function)? I am trying to set the value of the input from another function and this input is required in the validation so I cannot leave it empty and set the value on form submit?
So I need to setFieldValue from the function called getPriceUsingID because this function gets the price from the backend, How can I set the value of the price field?

import React from 'react';
import * as Yup from 'yup';
import { Formik } from 'formik';
import {
  Button,
  Grid,
  TextField,
} from '@material-ui/core';
import axios from 'axios';

const PriceCalculator = ({
  className,
  ...rest
}) => {

  const getPriceUsingID = async (id) => {
    let res = await axios.get('https://localhost/prices/'+id);
    let price = res.data.price;
    console.log(price);
  }

  return (
    <Formik
      enableReinitialize={true}
      initialValues={{
        productID: '',
        price: '',
      }}
      validationSchema={Yup.object().shape({
        productID: Yup.string().max(255).required('Amount is required'),
        price: Yup.string().max(255).required('Price is required'),
      })}
      onSubmit={async (values, {
        setErrors,
        setStatus,
        setSubmitting,
      }) => {
        try {
            console.log(values);
        } catch (err) {
          console.error(err);
          setStatus({ success: false });
          setErrors({ submit: err.message });
          setSubmitting(false);
        }
      }}
    >
      {({
        errors,
        handleBlur,
        handleChange,
        handleSubmit,
        isSubmitting,
        touched,
        values,
        setFieldValue
      }) => (
        <form
          onSubmit={handleSubmit}
          {...rest}
        >
          <Grid container> 
                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <TextField
                      error={Boolean(touched.productID && errors.productID)}
                      fullWidth
                      helperText={touched.productID && errors.productID}
                      label="Amount"
                      name="productID"
                      onBlur={handleBlur}
                      value={values.productID}
                      onChange={(e) => { handleChange(e); getPriceUsingID(e.target.value); }}
                      variant="outlined"
                    />
                  </Grid>
                  <Grid item xs={12}>
                    <TextField
                      error={Boolean(touched.price && errors.price)}
                      fullWidth
                      helperText={touched.price && errors.price}
                      label="Price"
                      name="price"
                      value={values.price}
                      onBlur={handleBlur}
                      onChange={handleChange}
                      variant="outlined"
                    />
                  </Grid>
                    <Button
                    color="secondary"
                    disabled                    type="submit"
                    variant="contained"
                    size="large"
                    >
                        Submit
                    </Button>
                </Grid>
            </Grid>
        </form>
      )}
    </Formik>
  );
};
export default PriceCalculator;

 

Comments

Mohamed Atef Date : 2021-07-03

Best answers

46

Best answers

46

Hey Joseph, there are two ways to achieve this,
The first way is by using setFieldValue inside the form and pass the Product ID to the outside function and return the price exactly like what you did in the code above 

  const getPriceUsingID = async (id) => {
    let res = await axios.get('https://localhost/prices/'+id);
    let price = res.data.price;
    console.log(price);
    return price;
  }

and the onChange function gonna look like this 

<TextField
  error={Boolean(touched.productID && errors.productID)}
  fullWidth
  helperText={touched.productID && errors.productID}
  label="Amount"
  name="productID"
  onBlur={handleBlur}
  value={values.productID}
  onChange={(e) => { handleChange(e); setFieldValue('price', getPriceUsingID(e.target.value)); }}
  variant="outlined"
/>

The second way is by passing the setFieldValue function to the outside function getPriceUsingID Like

  const getPriceUsingID = async (id, setFieldValue) => {
    let res = await axios.get('https://localhost/prices/'+id);
    let price = res.data.price;
    console.log(price);
    setFieldValue('price', price);
  }

and the field function gonna look like this 

<TextField
  error={Boolean(touched.productID && errors.productID)}
  fullWidth
  helperText={touched.productID && errors.productID}
  label="Amount"
  name="productID"
  onBlur={handleBlur}
  value={values.productID}
  onChange={(e) => { handleChange(e); getPriceUsingID(e.target.value, setFieldValue); }}
  variant="outlined"
/>

Note: you need to keep the price field as it is above, and it's gonna be fine, 
Hope you could figure out your issue 
Good Luck

Joseph Morgan Date : 2021-07-03

Amazing, this is really what I need 

Leave a comment

Join us

Join our community and get the chance to solve your code issues & share your opinion with us

Sign up Now

Related posts

React Redux : Connect is not called
Publish date: 2022-03-02 | Comments: 1

Tag: React js

npm install @mui/material returns error
Publish date: 2022-04-02 | Comments: 1

Tag: React js

Best way to update the state in one class component from the redux store?
Publish date: 2022-03-30 | Comments: 3

Tag: React js

How to use Datepick of Mui with Formik
Publish date: 2022-02-14 | Comments: 6

Tag: React js

Reload browser window using Reactjs?
Publish date: 2022-02-08 | Comments: 4

Tag: React js

React Component displaying a list of lines
Publish date: 2022-03-19 | Comments: 3

Tag: React js