Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loosing component data on page refresh in react

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

On click my developer tool image

When I refresh the page developer tool

like image 403
manish thakur Avatar asked Oct 27 '22 20:10

manish thakur


2 Answers

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:

  • https://medium.com/@akrush95/global-cached-state-in-react-using-hooks-context-and-local-storage-166eacf8ab46
  • https://github.com/aprilmintacpineda/react-context-api-store
  • https://www.robinwieruch.de/local-storage-react
  • https://dev.to/selbekk/persisting-your-react-state-in-9-lines-of-code-9go
  • ...
like image 159
Florian Motteau Avatar answered Nov 12 '22 18:11

Florian Motteau


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

like image 22
sbk201 Avatar answered Nov 12 '22 18:11

sbk201