首页 > 解决方案 > ReactJS:如何在组件之间同步 sessionStorage 状态

问题描述

在我的应用程序中,我有一个 React 组件,它呈现一个数字列表,它还通过sessionStorage.

我的应用程序还有一个组件,<input />可以添加新的数字。这也会导致存储的值sessionStorage被更新。对于每个数字,button存在 a 以允许删除数字,这会立即更新存储在 中的值sessionStorage

问题是我有另一个组件sessionStorage使用反应钩子将存储的值用作状态,但是当我更新状态值中sessionStorage的值时不会改变。

我正在尝试使用 更新它useEffect(),但它不起作用:

import React from 'react';
import { useState, useEffect } from "react";


const LimitsIndicator = props => {
  const {
    limits: { total, used },
    currency,
    t,
    type,
  } = props;


  const [limitInUse, setInUse] = useState(sessionStorage.getItem('inUse'));

  useEffect(() => {
    setInUse(sessionStorage.getItem('inUse'))
  })

  return (
    <div>{limitInUse}</div>
  )

}

在这张图片中,它显示了总和:250,以及两个值:100 和 150,但值 150 被取消了,正如您在控制台中看到的那样,sessionStorage更新了,但总和的值没有改变。

在此处输入图像描述

标签: javascriptreactjsreact-hooks

解决方案


在应用程序的不同部分之间实现状态同步的一种方法是通过 React 的Context API

一般的想法是limitInUse通过上下文提供者将共享状态(即)集中在应用程序的根组件处(或附近),然后包装需要通过相应的上下文使用者访问共享状态的子组件:

1.为共享状态创建上下文

创建一个上下文,它给我们一个状态“提供者”和一个状态“消费者”。上下文消费者将用于访问整个应用程序中的共享状态并与之交互:

const IsUseContext = React.createContext();

2.在根组件中定义共享状态的状态访问

limitInUse接下来,为共享状态定义获取/设置逻辑。这应该在应用程序根级别(或附近)的状态中定义。在这里,我在根组件state对象中定义它:

this.state = {
  /* Define initial value for shared limitInUse state */
  limitInUse : sessionStorage.getItem('inUse'),

  /* Define setter method by which limitInUse state is updated */
  setLimitInUse: (inUse) => {

    /* Persist data to session storage, and update state to trigger re-render */      
    sessionStorage.setItem('inUse', `${ inUse }`)
    this.setState({ limitInUse })
  },
}

3. 从根组件渲染上下文提供者

Provider现在,在应用程序的根级别渲染上下文的组件,并通过提供者的prop传递state对象。现在可以从应用程序中使用的任何上下文使用者访问value该对象(见下文):state

/* In your app component's render() method, wrap children with context provider */
<IsUseContext.Provider value={ this.state }>
  <LimitsIndicator />
  <InputComponent />
</IsUseContext.Provider>

4. 更新子组件中的共享状态

最后,我们通过上下文的消费者访问应用程序中嵌套子组件的共享limitInUse。请注意,传递给我们提供者的 prop 的对象中定义的 state 和 setter 方法value是可用且可访问的:

/* Update shared limitInUse state via context consumer */
return (<IsUseContext.Consumer>
  { ({ setLimitInUse }) => <input onChange={ 
     (event) => setLimitInUse(event.currentTarget.value) } />
  }
</IsUseContext.Consumer>)

在子组件中显示共享状态

/* Access shared limitInUse via context consumer */
return (<IsUseContext.Consumer>
  { ({ limitInUse }) => (<div>  {limitInUse} </div>) }
</IsUseContext.Consumer>)

有关完整的工作演示,请参阅此 jsFiddle。希望这可以帮助!


推荐阅读