6

我正在做一些我需要维护应用程序级别状态的事情,即全局状态,我正在为此使用反应钩子useContextuseReducer.

所以我正在做的是点击按钮,我正在设置我的上下文,然后通过在我的App.js.

我知道我为什么要使用我的数据,因为我首先将初始状态设置为 null,这就是为什么当我刷新页面时它再次设置为 null,但我的要求不是在单击按钮后我想将该数据存储为全局状态,以便我可以进一步使用它

但这不应该是我想让我的数据全球化并且在刷新时它不应该丢失的情况

我的代码

我的上下文文件

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 };

我设置上下文的家庭代码

    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;

还有我的 app.js 文件

    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>
  );
};

请检查工作代码我的代码和框链接

请检查反应开发者工具

单击我的开发人员工具图像

当我刷新页面开发者工具时

4

3 回答 3

2

要持久化 React 上下文、redux 存储或应用程序内存中的任何内容,您需要将其存储在外部,然后在应用程序启动时重新加载它(当您按 F5 时,页面会刷新,您的 React 应用程序会重新启动,所以它会丢失所有组件的状态、上下文、存储...)。

例如,您可以将上下文保存在本地存储中,然后修改您的上下文,以便它首先搜索存储的值并首先重新加载它。可以在您的上下文中使用 useEffect 来完成:每次更改时,将其存储在本地存储中,并在启动时预加载本地存储值:

// context
[...]

useEffect(() => {
  if(localStorage.getItem('myKey')) {
    setState(localStorage.getItem('myKey');
  }
}, []);

useEffect(() => {
  localStorage.setItem('myKey', state);
}, [state]);

这大致是可以做到的,它可以使用重构。

您还可以选择将上下文保存在远程服务器或本地 noSQL DB 上。你会发现很多解决方案:

于 2020-06-20T15:00:42.257 回答
1

从你的评论

本地存储不是一个好的选择我不想把这个值放在那里,因为任何人都可以删除它们,我只想保持状态反应

在这种情况下,LocalStorage 是客户端,react 是一个框架,也是客户端。客户端中的任何内容都可以以任何方式进行编辑。您不能在假设恶意意图的情况下依赖客户端的数据。如果 React 可以获取或编辑某些内容,那么任何具有 JS 知识的人都可以对其进行编辑。

您唯一可以信任的是您的后端服务器。客户端发送用户想要做的事情,服务器验证它然后处理请求,将结果发送回客户端。

您可以搜索此关键字以获取更多详细信息。

client server prevent cheat

于 2020-06-20T15:18:50.900 回答
0

缺少持久性机制。您可以扩展MyProvider函数,以便它从localStorage或 api获取值

API 示例


const MyProvider = props => {
  const [state, dispatch] = useReducer(MyReducer, initialstate);
  const click_btn = payload => {
    saveStateToApi(payload)
      .then(result => {
         dispatch({
           type: "BTNCLICKED",
           payload
         });
      })
  };

  useEffect(() => {
    getLastStateFromApi()
      .then(data => {
        dispatch({
          type: "BTNCLICKED",
          payload: data
        });
      })

  }, [])

  return (
    <MyContext.Provider
      value={{ someData: state.someData, click_btn }}
      {...props}
    />
  );
};
于 2020-06-20T14:55:32.157 回答