如何在React.js中刷新页面后维护状态?

Div*_*com 46 javascript reactjs

假设我有代码为上一页选择的选择框设置状态:

this.setState({selectedOption: 5});
Run Code Online (Sandbox Code Playgroud)

this.state.selectedOption页面刷新后有没有办法填充5?

是否有回调我可以用它来保存在localStorage中,然后做一个大的setState或者有一个标准的方法做这样的事情?

Div*_*com 37

所以我的解决方案是localStorage在设置状态时设置,然后localStorage再次从getInitialState回调中获取值,如下所示:

getInitialState: function() {
    var selectedOption = localStorage.getItem( 'SelectedOption' ) || 1;

    return {
        selectedOption: selectedOption
    };
},

setSelectedOption: function( option ) {
    localStorage.setItem( 'SelectedOption', option );
    this.setState( { selectedOption: option } );
}
Run Code Online (Sandbox Code Playgroud)

我不确定这是否可以被视为反模式,但它有效,除非有更好的解决方案.

  • 我认为这只是一个"反模式"的唯一部分是你的组件在localStorage中持久保存它自己的状态.如果多次使用此组件,则必须处理关键冲突.Imo,这个重要的信息(需要持久保存到localStorage)应该可以移动到应用程序架构中更高的状态或数据层......但这是完成工作的最简单方法,直到细节工作完成出 (30认同)
  • 如果将 `localStorage` 替换为 [`sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage),您将获得每个选项卡的单独状态,从而避免选项卡之间的冲突 (4认同)
  • 如果您想使用 localStorage 以在同一组件的多个实例中安全的方式保存状态,您可以为每个组件提供一个唯一的 ID,然后使用该 ID 作为 localStorage 中的键 - 就像``${this .props.id}.SelectedOption`` (2认同)

dan*_*ive 12

使用 Hooks 和 sessionStorage:

const [count, setCount] = useState(1);

  useEffect(() => {
    setCount(JSON.parse(window.sessionStorage.getItem("count")));
  }, []);

  useEffect(() => {
    window.sessionStorage.setItem("count", count);
  }, [count]);

  return (
    <div className="App">
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  );
Run Code Online (Sandbox Code Playgroud)

如果您仍然喜欢的话,请将 sessionStorage 替换为 localStorage。


jul*_*lez 11

你可以使用本地存储作为Omar Suggest"持久化"状态,但是应该在设置状态后完成.为此,您需要将回调传递给setState函数,并且需要序列化和反序列化放入本地存储的对象.

constructor(props) {
  super(props);
  this.state = {
    allProjects: JSON.parse(localStorage.getItem('allProjects')) || []
  }
}


addProject = (newProject) => {
  ...

  this.setState({
    allProjects: this.state.allProjects.concat(newProject)
  },() => {
    localStorage.setItem('allProjects', JSON.stringify(this.state.allProjects))
  });
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*and 7

我们有一个应用程序,允许用户在页面中设置“参数”。我们要做的是使用React Router(与History结合使用)和一个将JavaScript对象URI编码为可以用作查询字符串的格式的库,在URL上设置这些参数。

当用户选择一个选项时,我们可以通过以下方法将该值推入当前路线:

history.push({pathname: 'path/', search: '?' + Qs.stringify(params)});
Run Code Online (Sandbox Code Playgroud)

pathname可以是当前路径。您的情况params如下所示:

{
  selectedOption: 5
}
Run Code Online (Sandbox Code Playgroud)

然后在React树的顶层,React Router将props使用prop来更新该组件的location.search属性,该属性是我们之前设置的编码值,因此会有componentWillReceiveProps类似以下内容:

params = Qs.parse(nextProps.location.search.substring(1));
this.setState({selectedOption: params.selectedOption});
Run Code Online (Sandbox Code Playgroud)

然后,该组件及其子组件将使用更新的设置重新渲染。由于信息位于URL上,因此可以将其添加为书签(或通过电子邮件发送-这是我们的用例),并且刷新将使应用程序保持相同状态。对于我们的应用程序来说,这一直很好。

React Router:https : //github.com/reactjs/react-router

历史记录:https : //github.com/ReactTraining/history

查询字符串库:https : //github.com/ljharb/qs

  • 这应该是公认的解决方案,而不是保存到本地存储,这并不总是可行并且会减慢应用程序的速度。我将尝试应用此方法,谢谢。 (3认同)

小智 5

我认为状态仅适用于视图,而应该保留在视图状态之外的信息和数据最好作为道具存储。当您希望能够链接到页面或将URL共享到应用程序的深处但又使地址栏混乱时,URL参数非常有用。

看看Redux-Persist(如果您使用的是Redux)https://github.com/rt2zz/redux-persist