I am working on something where I need to maintain the application level state i.e global state, I am using react hooks for that useContext
and useReducer
.
So what I am doing is on button click I am setting up my context and then using it thought my application by registering the provider in my App.js
.
I know why I am using my data, because I am setting the initial state to null first, that's why when I refresh the page it sets to null again, but my requirement is not that after button click I want to store that data as a global state so that I can use it further
But this should not be the case I want to make my data global and on refresh it should not lose
My code
My context file
import React, { useReducer, createContext } from "react";
const initialstate = {
someData: null
};
const MyContext = createContext({
someData: null,
click_btn: d => {}
});
const MyReducer = (state, action) => {
switch (action.type) {
case "BTNCLICKED":
return {
...state,
someData: action.payload
};
default:
return state;
}
};
const MyProvider = props => {
const [state, dispatch] = useReducer(MyReducer, initialstate);
const click_btn = d => {
dispatch({
type: "BTNCLICKED",
payload: d
});
};
return (
<MyContext.Provider
value={{ someData: state.someData, click_btn }}
{...props}
/>
);
};
export { MyContext, MyProvider };
My home code where I am setting the context
import React, { useContext, useState } from "react";
import history from "../History/history";
import { MyContext } from "../context/testContext";
function Test() {
const context = useContext(MyContext);
const [data, setdata] = useState(null);
const clickEvt = () => {
setdata("Setting data");
context.click_btn(data);
};
return (
<div>
<input type="button" onClick={clickEvt} value="Click Me" />
</div>
);
}
export default Test;
And my app.js file
import React from "react";
import "./styles.css";
import { MyProvider } from "./context/testContext";
import { Router } from "react-router-dom";
import history from "./History/history";
import Routes from "./myRoutes";
export default () => {
return (
<MyProvider>
<Router history={history}>
<div className="App wrapper">
<Routes />
</div>
</Router>
</MyProvider>
);
};
Please do check working code My codesand box link
Please do check the react developer tools
To persist a React context, or a redux store or anything that lives in your app memory, you need to store it outside and then reload it when the app starts (when you press F5, the page is refreshed, your React app is restarted so it loses all components states, contexts, stores...).
You could save your context in local storage for instance, and modify your context so it starts by searching for a stored value and reload it first. It could be done using useEffect in your context : each time it changes, store it in local storage, and preload local storage value on startup:
// context
[...]
useEffect(() => {
if(localStorage.getItem('myKey')) {
setState(localStorage.getItem('myKey');
}
}, []);
useEffect(() => {
localStorage.setItem('myKey', state);
}, [state]);
This is roughly how it can be done.
You could also choose to persist your context on a remote server, or a local noSQL DB. You will find plenty of solutions:
From your comment
local storage is not a good option I don't want to put this values there as anybody can delete them, and I want to maintain the state in react only
In this case, LocalStorage is client side, react is a framework which is also client side. Anything in client side can be edited in any way. You can't rely data in client side, with assumption of malicious intend. If there's something React can get or edit, it can be edited by anyone who has JS knowledge.
The only thing you can trust is, your backend server. Client sends what user wants to do, and server valid it then handle the request, sends back the result to client.
You can search this keyword for more detail.
client server prevent cheat
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With