Skip to content

Instantly share code, notes, and snippets.

@mfrancois3k
Last active May 28, 2022 09:39
Show Gist options
  • Save mfrancois3k/4cc4d20431a5a7bec3cf45cc7befacd2 to your computer and use it in GitHub Desktop.
Save mfrancois3k/4cc4d20431a5a7bec3cf45cc7befacd2 to your computer and use it in GitHub Desktop.
useReducer and Context Together
store > global > CombinedContextProviders.js
//https://codesandbox.io/s/how-to-use-contex-use-reducer-use-memo-forked-zf1k65?file=/src/components/DisplayAuth.js:0-472
import ContextProviderComposer from "./ContextProviderComposer";
import { GlobalStateProvider } from "./global/global.provider";
const CombinedContextProviders = ({ children }) => {
return (
<ContextProviderComposer
contextProviders={[<GlobalStateProvider key={"global_state_provider"} />]}
>
{children}
</ContextProviderComposer>
);
};
export default CombinedContextProviders;
store > global > ContextProviderComposer.js
import React from "react";
const ContextProviderComposer = ({ contextProviders, children }) => {
return contextProviders.reduceRight(
(children, parent) => React.cloneElement(parent, { children }),
children
);
};
export default ContextProviderComposer;
import { useContext } from "react";
import { GlobalState } from "../store/global/global.state";
const DisplayAuth = () => {
console.log("re-render subcomponent");
const { isLoggedIn, login, logout } = useContext(GlobalState);
return (
<>
<div className="App">{isLoggedIn ? "Welcome back" : "Please login"}</div>
<button onClick={login}> Login </button>
<button onClick={logout}> Logout </button>
</>
);
};
export default DisplayAuth;
store > global > globalsState.js
import { useReducer, createContext } from "react";
// Define the initial state
const GLOBAL_STATE = {
isLoggedIn: undefined,
theme: "light",
isModalOpen: false,
pageBuilder: [],
create,
delete,
update
};
// Define the reducer
const globalReducer = (state, action) => {
switch (action.type) {
case "LOGIN":
return {
...state,
isLoggedIn: true
};
case "LOGOUT":
return {
...state,
isLoggedIn: false
};
case "LIGHT_THEME":
return {
...state,
theme: "light"
};
case "DARK_THEME":
return {
...state,
theme: "dark"
};
case "OPEN_MODAL":
return {
...state,
isModalOpen: true
};
case "CLOSE_MODAL":
return {
...state,
isModalOpen: false
};
case "CREATE_BUILDER":
return {
...state,
pageBuilder: {
...state.pageBuilder,
[action.payload.key]: action.payload
}
};
case "DELETE_BUILDER":
return {
...state,
pageBuilder: state.pageBuilder.filter(
(builder) => builder._id !== action.payload
),
loading: false
};
case "UPDATE_BUILDER":
return {
...state,
pageBuilder: {
...state.pageBuilder,
[action.payload.key]: action.payload
}
};
default:
return state;
}
};
// Create the context
export const GlobalState = createContext();
GlobalState.displayName = "GlobalState";
export const GlobalStateProvider = ({ children }) => {
// Create the reducer
const [state, dispatch] = useReducer(globalReducer, GLOBAL_STATE);
const value = {
...state,
login: () => {
dispatch({ type: "LOGIN" });
},
logout: () => {
dispatch({ type: "LOGOUT" });
},
setLightTheme: () => {
dispatch({ type: "LIGHT_THEME" });
},
setDarkTheme: () => {
dispatch({ type: "DARK_THEME" });
},
openModal: () => {
dispatch({ type: "OPEN_MODAL" });
},
closeModal: () => {
dispatch({ type: "CLOSE_MODAL" });
},
create_builder: () => {
dispatch({ type: "CREATE_BUILDER" });
},
delete_builder: () => {
dispatch({ type: "DELETE_BUILDER" });
},
update_builder: () => {
dispatch({ type: "UPDATE_BUILDER" });
}
};
// Wrap the context provider around our component
return <GlobalState.Provider value={value}>{children}</GlobalState.Provider>;
};
// import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import CombinedContextProviders from "./store/CombinedContextProviders";
// import { GlobalStateProvider } from "./store/global/global.provider";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
// <GlobalStateProvider>
<CombinedContextProviders>
<App />
</CombinedContextProviders>
// </GlobalStateProvider>
);
/ import { useContext } from "react";
import DisplayAuth from "./components/DisplayAuth";
// import { GlobalState } from "./store/global/global.state";
import "./styles.css";
export default function App() {
console.log("re-render root app");
// const { isLoggedIn, login, logout } = useContext(GlobalState);
return (
<>
<DisplayAuth />
{/* <div className="App">{isLoggedIn ? "Welcome back" : "Please login"}</div> */}
{/* <button onClick={login}> Login </button>
<button onClick={logout}> Logout </button> */}
</>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment