Skip to content

Instantly share code, notes, and snippets.

@VineetKumarKushwaha
Last active June 27, 2020 18:02
Show Gist options
  • Save VineetKumarKushwaha/dacc8c122a4647c9ad077c53ef38d97d to your computer and use it in GitHub Desktop.
Save VineetKumarKushwaha/dacc8c122a4647c9ad077c53ef38d97d to your computer and use it in GitHub Desktop.
React Context Provider Pattern
import React, { useEffect } from "react";
const initialState = {
user: null,
loading: false,
errorMessage: ""
};
const UserContext = React.createContext();
const userReducer = (state, action) => {
switch (action.type) {
case "loading": {
return { ...state, loading: true };
}
case "fetched": {
return {
...state,
loading: false,
user: action.payload
};
}
case "failed": {
return {
...state,
loading: false,
errorMessage: action.payload
};
}
case "updateName": {
return {
...state,
user: { ...state.user, name: action.payload }
};
}
case "updatePhone": {
return {
...state,
user: { ...state.user, phone: action.payload }
};
}
case "updateAddress": {
return {
...state,
user: {
...state.user,
address: { ...state.user.address, ...action.payload }
}
};
}
default: {
throw new Error(`Unhandled action type: ${action.type}`);
}
}
};
const UserProvider = ({ children }) => {
const [state, dispatch] = React.useReducer(userReducer, initialState);
useEffect(() => {
(async () => {
dispatch({ type: "loading" });
try {
const user = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
name: "Test User",
gender: "Male",
phone: "+910000000000",
address: {
building: "2030",
street: "something something",
location: "Some",
country: "India"
}
});
}, Math.ceil(Math.random() * 1000));
});
dispatch({ type: "fetched", payload: user });
} catch (error) {
dispatch({ type: "failed", errorMessage: "Not able to fetch user" });
}
})();
}, [dispatch]);
return (
<>
{state.loading && <h1>Fetching User...</h1>}
{state.errorMessage && <h1>{state.errorMessage}</h1>}
{state.user && (
<UserContext.Provider value={{ state, dispatch }}>
{children}
</UserContext.Provider>
)}
</>
);
};
const useUser = () => {
const context = React.useContext(UserContext);
if (context === undefined) {
throw new Error("Error");
}
return context;
};
export { UserProvider, useUser };
import React from "react";
import { useUser, UserProvider } from "./user-context";
const Address = () => {
const {
state: {
user: { address }
}
} = useUser();
return (
<>
<h3>
{address.building}, {address.street}
</h3>
<h3>
{address.location}, {address.country}
</h3>
</>
);
};
const Information = () => {
const {
state: { user }
} = useUser();
return (
<h2>
{user.name}, {user.gender}, {user.phone}
</h2>
);
};
const Display = () => {
return (
<div className="displayCard">
<Information />
<Address />
</div>
);
};
const EditableInformation = () => {
const {
state: { user },
dispatch
} = useUser();
return (
<div className="personal">
Name:{" "}
<input
value={user.name}
type="text"
onChange={e =>
dispatch({ type: "updateName", payload: e.target.value })
}
/>
Name:{" "}
<input
type="text"
value={user.phone}
onChange={e =>
dispatch({ type: "updatePhone", payload: e.target.value })
}
/>
</div>
);
};
const Editable = () => {
return (
<div className="editable">
<EditableInformation />
</div>
);
};
export default function App() {
return (
<div className="App">
<UserProvider>
<Display />
<Editable />
</UserProvider>
</div>
);
}
@VineetKumarKushwaha
Copy link
Author

VineetKumarKushwaha commented Jun 27, 2020

54529ffa-8cfe-48b6-a362-839ff2f046f4
Consumers are components and all their children will inherently become the consumer.

@VineetKumarKushwaha
Copy link
Author

VineetKumarKushwaha commented Jun 27, 2020

Working Example is here
In this, I have implemented both the things, you can read the user information through the context API, and also you can update it though I would not suggest to do the write operation like this.

IMO, Context API is very useful for a read-only state like logged in user information or preferred language across the application.
Although when we allow update from the child components, it might create a mess plus it would cause difficulties while debugging like who changed the state and when.

Click here for more information

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment