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.
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.
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>
);
}
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With