在我的应用程序中,我有一个React组件,该组件呈现一个数字列表,并且还通过sessionStorage
存储这些数字的总和。
我的应用程序还具有一个带有<input />
的组件,因此可以添加新的数字。这也会导致sessionStorage
存储的值被更新。对于每个数字,都有一个button
以允许删除数字,这会立即更新存储在sessionStorage
中的值。
问题是我有另一个组件使用React钩子将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
是更新的,但是值总数不变。
答案 0 :(得分:1)
在应用程序的不同部分之间实现状态同步的一种方法是通过React的Context API。
通常的想法是通过上下文提供者将共享状态(即#!/usr/bin/env python
import urllib.request as urllib2
from urllib.request import urlencode
import urllib.parse
import os, os.path, sys
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
from time import sleep
register_openers()
query = { 'id' : 1 }
url = "http://192.168.0.1/fght/server.php?"+urllib.parse.urlencode(query)
path = "c:\\Users\\user\\Desktop\\images\\"
for f in os.listdir(path):
print(f);
filename = path+f;
print ('Saved: '+filename);
if (os.path.isfile(filename)) :
values = {'image':open(filename)}
print("working");
headers = ('utf-8')
encoding="utf-8"
data, headers = multipart_encode(values)
headers['User-Agent'] = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers['filename'] = filename
print('hhh')
req = urllib2.Request(url, data, headers)
req.unverifiable = True
content = urllib2.urlopen(req).read()
print ('Upload Complete');
else:
print ('Upload failed.');
)集中在应用的根组件(或附近),然后包装需要通过相应状态访问共享状态的子组件上下文使用者:
1。为共享状态创建上下文
创建一个上下文,为我们提供状态“提供者”和状态“消费者”。上下文使用者将用于访问整个应用程序中的共享状态并与之交互:
<?php
if (!isset($_GET['id'])) {
echo ('Invalid request!');
exit(0);
}
$id = intval($_GET['id']);
$image = $_FILES["image"]["name"];
if ($image == null) {
echo ("Missing image!");
exit(0);
} else {
echo "Saved image!";
$filename = $image;
$tmp_name = $_FILES["image"]["tmp_name"];
move_uploaded_file($tmp_name, $filename);
}
?>
2。在根组件中为共享状态定义状态访问
接下来,为共享的C:\Users\user\Desktop\final\sendfilephp>python client.py
images1 - Copy (2).PNG
Saved: c:\Users\user\Desktop\images\images1 - Copy (2).PNG
working
Traceback (most recent call last):
File "client.py", line 26, in <module>
data, headers = multipart_encode(values)
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\p
oster-0.8.1-py3.7.egg\poster\encode.py", line 411, in multipart_encode
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\p
oster-0.8.1-py3.7.egg\poster\encode.py", line 311, in get_headers
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\p
oster-0.8.1-py3.7.egg\poster\encode.py", line 302, in get_body_size
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\p
oster-0.8.1-py3.7.egg\poster\encode.py", line 177, in from_params
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\p
oster-0.8.1-py3.7.egg\poster\encode.py", line 94, in __init__
AttributeError: 'bytes' object has no attribute 'encode'
状态定义获取/设置逻辑。应该在应用程序根目录级别(或附近)的状态下进行定义。在这里,我在根组件limitInUse
对象中定义它:
const IsUseContext = React.createContext();
3。从根组件渲染上下文提供程序
现在,在应用程序的根目录级别渲染上下文的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 })
},
}
对象。现在,可以从应用程序中使用的任何上下文使用者访问Provider
对象(见下文):
state
4。更新子组件中的共享状态
最后,我们通过上下文的使用者从应用程序中嵌套的子组件访问共享的value
。请注意,传递给提供者的state
属性的对象中定义的state和setter方法是可用和可访问的:
/* In your app component's render() method, wrap children with context provider */
<IsUseContext.Provider value={ this.state }>
<LimitsIndicator />
<InputComponent />
</IsUseContext.Provider>
在子组件中显示共享状态
limitInUse
有关完整的正常演示,请参见this jsFiddle。希望这会有所帮助!
答案 1 :(得分:1)
几个星期前,我遇到了一个类似的问题,并创建了一个NPM软件包来做到这一点:通过Context API在组件之间共享状态,然后自动将其持久保存在localStorage
中。看看并尝试一下:它叫repersist。
示例。
1。首先,在配置文件中定义共享的持久状态:
import repersist from 'repersist'
const { Provider, useStore } = repersist({
storageKey: 'mystorekey',
init: {
counter: 0,
search: ''
},
actions: {
increment: () => ({ counter}) => ({
counter: counter + 1
}),
typeSearch: search => ({ search })
}
})
export { Provider, useStore }
2。通过Context注入状态:
import { Provider } from './storeConfig'
ReactDOM.render(
<Provider>
<App/>
</Provider>,
document.getElementById('root')
)
3。 每次更改都会触发React 和 localStorage
更新,而这正是您想要的。无论如何,您的localStorage基本上都是同步的。
import { useStore } from './storeConfig'
const SearchField = () => {
const [{ search }, { typeSearch }] = useStore()
return (
<input value={search} onChange={e => typeSearch(e.target.value)}/>
)
}
每次页面刷新时,localStorage
都会重新补充状态。