Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Formik setFieldValue Inside a Function

If I have a functional component and want to set a value outside of the Formik tag, how would I do that? Below is the code that I have for further clarification.

function XYZScreen() {

    const someFunctionWithLogic = () => {
        // Set the value of the number field here...
    }
    
    return (
        <Screen>
            <Formik>
                <FormField name="number" placeholder="Number" />
             </Formik>
        </Screen>            
    );
}

I have reduced the code to as little as possible to simplify the question. The question might not make sense in the context of the question but I think it is clear what I am asking for.

If you need more code, please let me know, I am happy to provide it if needed.

like image 446
Tom el Safadi Avatar asked Dec 12 '25 06:12

Tom el Safadi


2 Answers

You can use the useFormik hook instead:

import { useFormik } from 'Formik'

function XYZScreen() {

    const formikProps = useFormik({
        initialValues,
        validationSchema,
        onSubmit: yourSubmitFunction,
        ...etc
    })

    const someFunctionWithLogic = () => {
        // Set the value of the number field here:
        formikProps.setFieldValue("number", someNumber)
    }
    
    return (
        <Screen>
            {/* No need for Formik component */}
            <FormField 
                name="number" 
                placeholder="Number" 
                value={formikProps.values.number} // or whatever the value is
                onChange={formikProps.handleChange}
            />
        </Screen>            
    );
}

So you're basically setting up all your form props in the function body, and you have access to them there. Formik has a lot of great helper hooks and functions, I highly recommend combing through the docs.

Edit: Another way

If you really like the Formik tag, you can keep using it. Just create a Formik wrapper component, and use your custom logic in a descendant using useFormikContext:

// FormWrapper.js

const FormWrapper = () => (
  <Formik
    initialValues={initialValues}
    validationSchema={validationSchema}
    onSubmit={yourOnSubmitFunction}
  >
    <SomeChild />
  </Formik>
)

// SomeChild.js

const SomeChild = () => {

  // returns all values and methods from your Formik tag
  const formikProps = useFormikContext()

  const someFunctionWithLogic = () => {
    formikProps.setFieldValue("number", someNumber)
  }
    
  return (
    <Screen>
      <FormField 
        name="number" 
        placeholder="Number" 
        value={formikProps.values.number} // or whatever the value is
        onChange={formikProps.handleChange}
      />
    </Screen>            
    );
}
like image 76
Seth Lutske Avatar answered Dec 14 '25 20:12

Seth Lutske


I just faced similar issue myself, and came up with another solution extending comment from Seth Lutske. You could combine using useFormik together with manual creation of Formik context. useFormik is very powerful, but it's downside is that it does not create a context, thus you cannot use useField or useFormikContext in child components, and need to manually pass them all the related props (value, onChange, onBlur etc).

What you can do is to create a Formik context object using useFormik, and pass context down manually using <FormikProvider>. With this approach, you can continue using all the fields as if they were wrapped in <Formik>

import { useFormik, FormikProvider } from 'formik'

function XYZScreen() {
    const formikProps = useFormik({
        initialValues,
        validationSchema,
        onSubmit: yourSubmitFunction,
        ...etc
    })

    const someFunctionWithLogic = () => {
        // Set the value of the number field here:
        formikProps.setFieldValue("number", someNumber)
    }
    
    return (
        <Screen>
          {/* FormikProvider component instead of Formik */}
          <FormikProvider value={formikProps}>  
            <FormField 
              name="number" 
              placeholder="Number" 
            />
          </FormikProvider>  
        </Screen>            
    );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
like image 33
Андрей Козюля Avatar answered Dec 14 '25 22:12

Андрей Козюля