Streamlining React forms: Component-level optimization with Formik provider
Formik is a popular form management library in the React ecosystem that simplifies the process of building and handling forms. One of its powerful features is the ability to provide a centralized state management system for form fields.
Understanding Formik
Formik is designed to keep the state of your form elements in sync with React's state. It provides a set of hooks and components that make it easy to manage form state, validate input, handle form submission, and more. Formik uses the Context API in React to manage and share the form state efficiently across the component tree.
Drilling down Formik fields
Nowadays, we break our React application into smaller pieces, which helps us contribute better to modularity, debugging, reusability, maintainability, testing, performance optimization, etc. So, while we have multiple components, we tend to come across situations where we use nested components, and we need to drill down values to the child component, which sometimes creates certain issues. This blog discusses one such issue where each form section is split into different components containing several form fields. While passing down a collection of arrays or objects, we use the <FieldArray /> component that handles array list/manipulations. It throws a TypeError when Formik and its values are drilled down to a nested component.
Benefits of drilling down Formik fields
- Cleaner component structure:
- It avoids prop drilling and keeps your component tree clean.
- Components only need to access the relevant form state and actions without being concerned about the overall form structure.
- Easier maintenance:
- The form structure or state management changes are isolated to the Formik Provider, reducing the impact on individual components.
- Improved reusability:
- Encourages the creation of reusable form-related components that can be easily integrated into different parts of your application.
Following is the code snippet where Formik is drilled down to nested component for form field <FieldArray />
import MainComponent from "./components/MainComponent"; function App() { return ( <div> <MainComponent /> </div> ); } export default App;
import React from "react"; import { useFormik, FormikProvider } from "formik"; import ChildComponent from "./ChildComponent"; const MainComponent = () => { const formik = useFormik({ initialValues: { demoField: [] } }); React.useEffect(() => { formik.setFieldValue("demoField", [ { message: "Message 1" }, { message: "Message 2" }, { message: "Message 3" }, ]); }, []); return ( <FormikProvider value={formik}> <ChildComponent formik={formik} />{" "} </FormikProvider> ); }; export default MainComponent;
MainComponent.jsx is the parent component where the main Formik is created. From that component, Formik is drilled down to the child component.
import React from "react"; import { FieldArray, Field } from "formik"; import "./style.css"; const ChildComponent = ({ formik }) => { return ( <FieldArray name="marketingMessage" render={(arrayHelpers) => formik.values.demoField ? formik.values.demoField.map((template, index) => ( <> <div> <Field name={`demoField[${index}].message`} /> </div> </> )) : null } ></FieldArray> ); }; export default ChildComponent;
ChildComponent.jsx is the child component that uses the Formik of the main component.
When the above snippet is executed, we face certain runtime errors.
There could be several reasons why drilling down Formik as a prop might not work:
• The child component is trying to access values before it is being assigned
• Missing React context above any component that utilizes Formik and, by extension, Formik's context.
We can use useFormik and FormikProvider together instead of the render prop <Formik> going forward. Field and other context-based components can be easily used without ceremony or added verbosity. It also lets folks efficiently create effects with useEffect.
The role of Formik provider
The concept of a "Formik Provider" might not be explicitly mentioned in the Formik library documentation. However, "Provider" typically refers to a part of Formik that utilizes the React Context API to make the Formik state and functions available to the entire component tree without prop drilling. The Formik Provider wraps your entire form component tree, enabling any child component to access the form state and actions.
Following is the updated code snippet for the Parent component
import React from "react"; import { useFormik, FormikProvider } from "formik"; import ChildComponent from "./ChildComponent"; const MainComponent = () => { const formik = useFormik({ initialValues: { demoField: [] } }); React.useEffect(() => { formik.setFieldValue("demoField", [ { message: "Message 1" }, { message: "Message 2" }, { message: "Message 3" }, ]); }, []); return ( <FormikProvider value={formik}> <ChildComponent formik={formik} />{" "} </FormikProvider> ); }; export default MainComponent;
Benefits of Formik provider
- Global accessibility: Components nested within the Formik component can easily access the form state, form values, and form-related functions without explicitly passing them as props.
- Simplified component structure: The Formik Provider simplifies the component structure by avoiding the need to pass form-related props down through multiple levels of components, leading to cleaner and more readable code.
- Easier maintenance: The form structure or state management changes are isolated to the Formik Provider, reducing the impact on individual components. This makes the codebase easier to maintain.
- Improved reusability: Encourages the creation of reusable form-related components that can be easily integrated into different parts of your application, thanks to the centralized form state management.
- Efficient updates with React context: Leveraging React Context allows for efficient updates and re-renders only when necessary. Components subscribed to the form context are updated only when the relevant form state changes.
Drill down Formik fields to React components with Formik provider and optimize React form development:
Drilling down Formik fields to React components using the Formik Provider is a powerful technique to streamline form management in your React applications. By leveraging the capabilities of the Formik Provider, you can build scalable, maintainable, and reusable forms while keeping your component tree organized and efficient.
Formik's combination of simplicity and flexibility and the Formik Provider make it a valuable tool for managing forms in React applications. As you continue to work with Formik, exploring advanced techniques like drilling down Formik fields will enhance your ability to build robust and user-friendly forms.