redux调度将其他状态重置为默认状态



摘要

我有两个状态:isLoggedcounterisLogged是一个布尔,用户可以将其设置为true或false,这样做时,如果isLogged设置为true,用户可以访问某些页面。counter只是一个简单的int,用户可以在其中递增/递减。如果两个状态的值发生变化,它们都会保存在sessionStorage上;在init上,我运行了一个分派,从sessionstorage中获取这两个值。isLogged的默认值为falsecounter0

问题

举个例子,我们有这样的状态值:
isLogged = true
counter = 4

如果我尝试调用increment操作,那么现在的值将是:

isLogged = false
counter = 5

如您所见,它将isLogged重置为其默认值。然而,当我在Chrome上查看sessionstorage面板时,它显示:{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中读取。

最新更新