javascript - redux dispatch 将其他状态重置为默认值
问题描述
概括
我有 2 个状态:isLogged
和counter
. isLogged
是一个布尔值,用户可以将其设置为 true 或 false,这样做用户可以访问 ifisLogged
设置为 true 的某些页面。这counter
只是一个简单的 int,用户可以在其中递增/递减它。sessionStorage
如果它们的值发生变化,这两种状态都会被保存;在初始化时,我运行了一个调度以从sessionstorage
. isLogged
的默认值为false
和。
counter
0
问题
假设我们有这个状态值:isLogged = true
counter = 4
如果我尝试调用一个increment
动作,现在的值将是:
isLogged = false
counter = 5
如您所见,它将 重置isLogged
为其默认值。但是,当我sessionstorage
在 Chrome 上查看面板时,它会说:{isLogged: true, counter: 5}
所以它仍在保存值,sessonstorage
并且那里的一切似乎都工作正常。但是在应用程序本身上,它说isLogged
现在是现在false
,即使他出于某种原因没有注销,用户也无法再访问某些页面。
奇怪的是,如果我刷新页面,现在的状态是:
isLogged = true
counter = 5
(当然数据是从 中获取的sessionstorage
)但是如果我现在切换isLogged
到false
,它也会重置counter
到0
:
isLogged = false
counter = 0
所以问题是当我调用调度/动作来修改某个状态时,所有其他状态都会被重置。
代码
src/actions/index.js
export const increment = (num) => {
return {
type: 'INCREMENT',
payload: num
}
}
export const decrement = () => {
return {
type: 'DECREMENT'
}
}
export const get_data = () => {
return {
type: 'GET'
}
}
export const signin = () => {
return {
type: 'SIGN_IN'
}
}
export const signout = () => {
return {
type: 'SIGN_OUT'
}
}
export const getlogged = () => {
return {
type: 'GET'
}
}
src/reducers/counter.js
const counterReducer = (state = 0, action) => {
switch(action.type) {
case 'INCREMENT':
state += action.payload
saveCounter(state)
return state
case 'DECREMENT':
state -= 1
saveCounter(state)
return state
case 'GET':
state = getCounter()
return state
default:
return 0
}
}
const saveCounter = (state) => {
const data = {
counter: state
}
sessionStorage.setItem("data", JSON.stringify(data))
}
const getCounter = () => {
if (sessionStorage.getItem("data") != null) {
const data = JSON.parse(sessionStorage.getItem("data"))
return data["counter"]
}
else {
return 0
}
}
export default counterReducer
src/reducers/isLogged.js
const loggedReducer = (state = false, action) => {
switch(action.type) {
case 'SIGN_IN':
state = true
saveLogged(state)
return state
case 'SIGN_OUT':
state = false
saveLogged(state)
return state
case 'GET':
state = getLogged()
return state
default:
return false
}
}
const saveLogged = (state) => {
const data = {isLogged: state}
sessionStorage.setItem("logged", JSON.stringify(data))
}
const getLogged = () => {
if (sessionStorage.getItem("logged") != null) {
const data = JSON.parse(sessionStorage.getItem("logged"))
return data["isLogged"]
}
else {
return false
}
}
export default loggedReducer
我在这样的组件上调用它:
useEffect(() => {
getCounter()
}, [])
const counter = useSelector(state => state.counter)
const dispatch = useDispatch()
const getCounter = () => {
dispatch(get_data())
}
return (
<div className="container-fluid mt-3">
<p className="text-white">Counter: {counter}</p>
<button onClick={() => dispatch(increment(4))} className="btn btn-primary">+</button>
<button onClick={() => dispatch(decrement())} className="btn btn-danger">-</button>
</div>
)
解决方案
问题在于,在您的两个减速器中,您在默认情况下都返回了默认状态。这意味着每个未处理的操作都会重置状态。
例如,当您调度一个增量操作时,它会在您的 reducer 中进入默认状态并将状态设置为 false。
默认情况下应该简单地返回未更改的状态。
除此之外,你的 useEffect 似乎有点危险,因为 getCounter 在每次渲染时都会发生变化,每次都会调用它。
如果你想在 localStorage 中保存一些东西,我还建议你使用 redux 的中间件。reducer 应该是一个没有副作用的函数,所以你不尊重这里的规则。您也不应该通过操作从 localStorage 读取,而是在创建商店时从 localStorage 读取。
推荐阅读
- linux - 无法在 squid 代理后面下载软件包列表
- linux - 如何使用模糊搜索配置 Elasticsearch
- javascript - 无法删除动态创建的 SVG 路径
- flutter - 在开发通道中升级 Flutter 后出错,getter X 没有为类 X 定义
- c++ - Python3 调用 C++ 函数(名称修改问题)
- spring - 如何使用 Javers 通过自定义更新方法进行审核?
- linux - 查询 clang 代码覆盖率和 gcov 版本
- python - 从 javascripr/浏览器调用 Python 函数
- node.js - 通过 CarboneJS 使用我自己的存储在数据库中的模板
- python - cv2.waitKey() 适用于“q”键,但不适用于任何其他键