javascript - 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
更新了,但总和的值没有改变。
解决方案
在应用程序的不同部分之间实现状态同步的一种方法是通过 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。希望这可以帮助!
推荐阅读
- listview - 如何在用户的表单视图中显示列表视图更改历史记录?(奥多 13)
- swift - " NSLocalizedDescription = "神经网络中输出层 'Identity' 的大小与分类器中的类数不匹配。"
- python - 我该如何处理这个 PEP8 警告?
- linux - 为什么“xargs sudo perf top”没有按预期工作?
- azure-data-factory-2 - Azure 数据工厂,如何提供管道计划日期作为活动的价值
- swift - Sequence.compactMap 等效于具有可选值的元组
- aws-sdk-go - 使用 s3manager.Downloader 的推荐方法是什么?
- php - 如何在 Laravel 7 上正确使用 dompdf?
- jenkins - 从 Jenkins 插件访问 Jenkins 设置的环境变量
- javascript - Axios 取消异步