Use React Context API against prop drilling and for modularizing your app
Prop drilling is a readability annoyance going on from the date ReactJS got published the first time. This is a simple example:
const GrandParent = () => {
<Parent childId={123} />
}const Parent = ({childId}) => {
<Child id={childId} />
}const Child = ({id}) => {
<div id={id} />
}
We need to use this kind of ugly code mostly for our forms and it is intuitively required while refactoring work is done. In all likelihood using a global store like Redux is not a modularized approach. We need to create a tree-like composition similar to a federal state: govern and decide as near to the subject as possible.
Before going on you should take a look at the Ternary design system to profoundly understand the core principles. Don’t forget to clap :)
Here is the folder structure of the standard that we are going to elucidate:
This path will grant you a highly modularized technique. You can use Redux for global actions and Context API for file-based state modifications. You are required to name your context and provider as the name of the component. Contact -> ContactContext, HomePage -> HomePageContext. Imagine your base folder (Contact) as a federated state that has its own government and is also dependent on the central government (Redux etc.).
Let’s see some code examples.
ContactContext.js
import { createContext } from 'react';
const ContactContext = createContext(null);
export default ContactContext;
ContactProvider.js
import React from 'react';
import ContactContext from './ContactContext';
import useContactForm from './hooks/useContactForm';const ContactProvider = ({ children }) => {
const { contactFormProps } = useContactForm(); return (
<ContactContext.Provider value={{ ...contactFormProps }}>
{children}
</ContactContext.Provider>
);};export default ContactProvider;
hooks/useContactForm.js
import { useState } from 'react';const useContactForm = () => {
const [contactForm, setContactForm] = useState({
name: '',email: '',message: ''
}); /**
* For validation and other middle tasks we use
* a controller function
* In this example we settle form values.
*/
const contactFormController = (target) => {
const {name, value} = target;
setContactForm({
...contactForm,
[name]: value
});
}; return {
contactFormProps: {
contactForm,
contactFormController
},
};};export default useContactForm;
Let’s wrap our Contact component using the provider
import React from 'react';
import { Form } from './ui/partials';
import { ContactProvider } from './common/context/ContactProvider';const Contact = () => {
return (
<ContactProvider>
<Form />
</ContactProvider>
);};export default Contact;
Eventually, our context is ready to be used by our contact form.
...
const { contactForm, contactFormController } =
useContext(ContactContext);return (
<input name="name" value={contactForm.name} onChange={contactFormController}/>
<input name="email" value={contactForm.email} onChange={contactFormController}/>
<textarea name="message" value={contactForm.message} onChange={contactFormController}/>
...
If you like this publication, please clap and share.
What do you think? Is Context API still useful?