Implementation of createContext using custom hooks
Prerequisites
React knowledge
Why we need context ?
Sharing of data across components with out the use of any state management libraries like redux or other storages like localStorage.
The code
Assuming we have scaffolded a basic reactjs app using create-react-app
Create a context (MyContext.jsx) in src/context folder
import React, { useState } from "react";
const MyContext = React.createContext();const defaultValue = {
name: "No name defined",
weapon: "No weapon defined"
};export const MyContextProvider = ({ children, initialData }) => {const [value, setValue] = useState(initialData || defaultValue);const saveValue = (values) => { setValue(values) };return (
<MyContext.Provider value={{ avengerData: value, saveValue }}> {children}
</MyContext.Provider>
);
};export default MyContext;
we have a state variable (value)and it change modifier (setValue) defined. Using context we are providing the value and the modifier function to its children.
Now lets create a custom hook (userAvengers.js) in src/hooks and import the above context in the hook
import { useContext } from "react";
import MyContext from "../context/MyContext"; // import the contextconst UseAvenger = () => {
const context = useContext(MyContext);
return context;
};
export default UseAvenger;
Now we can use this context. Here im using this context for the entire application so I'm modifying my src/index.js like this
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { MyContextProvider } from './context/MyContext';const root = ReactDOM.createRoot(document.getElementById('root'));const defaultValue = {name: "Captain America",weapon: "Shield"};root.render(
<MyContextProvider initialData={defaultValue}>
<App />
</MyContextProvider>
);
Here we have wrapped the entire application <App /> in MyContextProvider and passed a default value as initialData to the context provider
In App.jsx we consumed the context using the custom hook useAvengers and we used one more component AnotherComponent which modifies the context data
App.js
import UseAvenger from './hooks/useAvengers';
import AnotherComponent from './components/AnotherComponent';function App() {
const { avengerData } = UseAvenger();
return (
<div style={{border:'2px solid #F8C565', padding:'5px', margin:'5px'}}><p>The current Avenger is <strong>{avengerData.name}</strong>, and the weapon is <strong>{avengerData.weapon}</strong></p><AnotherComponent />
</div>
);
}
export default App;
AnotherComponent.jsx
import UseAvenger from '../hooks/useAvengers';
import React, {useEffect} from 'react';function AnotherComponent() {
const { avengerData, saveValue } = UseAvenger();
const changeAvengers = () => {saveValue({ name: "Tony stark", weapon: "Arc" });
};
return (
<div style={{border:'2px solid #e3e3e3', padding:'5px', margin:'5px'}}>
<strong>Another component</strong>
<p>The current Avenger is <strong>{avengerData.name}</strong>, and the weapon is <strong>{avengerData.weapon}</strong></p><div><button onClick={() => {changeAvengers()}}>Change</button>/div></div>);
}
export default AnotherComponent;
When we click on the change button we are calling the changeAvengers function which in turn calls the saveValue function which is a context provider functionality that modifies the context data. When the data is successfully modified both the App and AnotherComponent will gets the new data.
Initial load we get the following data
After clicking change
Conclusion
A robust way of sharing data across components if you are not using any state management libraries or you have a lot of nested components to pass the props.