【发布时间】:2020-03-24 12:30:46
【问题描述】:
当我更新费用时,它不会触发 useEffect 将数据存储在本地存储中。
import React, { useState, useEffect } from 'react';
export const ExpenseContext = React.createContext();
const ExpenseState = (props) => {
const [state, setState] = useState(
() => JSON.parse(localStorage.getItem('expenses')) || []
);
useEffect(() => {
console.log('didUpdate', state)
state.length !== 0 && localStorage.setItem('expenses', JSON.stringify(state));
}, [state])
function addExpense({id, name, category, value, note, date}){
const expense = state.find(exp => exp.id === id);
if(!expense){
setState(state => ([...state, {id, name, category, value, note, date}]))
}else{
const updatedExpense = state.map(exp => {
if(exp.id === expense.id){
return {
...exp,
...{id, name, category, value, note, date}
}
}else{
return exp
}
})
setState(updatedExpense)
}
console.log(state)
}
return (
<ExpenseContext.Provider
value={{
expenses: state,
addExpense: addExpense,
}}
>
{props.children}
</ExpenseContext.Provider>
)
}
我正在为数组的每个元素调用 addExpense。假设我们有 4 个费用存储在存储中。现在我们更新了一项费用,然后运行下面的代码。
for(const expense of expenses){
expenseContext.addExpense(expense);
}
现在只有最后一个元素才会触发使用效果,并且费用也不会在上下文中更新。
【问题讨论】:
-
请用 runnable minimal reproducible example 更新您的问题,使用 Stack Snippets(
[<>]工具栏按钮)演示问题。 Stack Snippets 支持 React,包括 JSX; here's how to do one. -
当然,it's documented - 在被链接的页面上 - 它用于延迟初始化状态
-
谢谢@mfeineis!不过,
|| []仍然是不必要的,对吧?useState从不返回虚假值。 -
不,这也很好,这似乎是通过
JSON.parse(localStorage.getItem("expenses"))找不到数据时的初始情况的后备方案。我把代码放到一个codesandbox中,似乎工作得很好,虽然最好useCallback回调,显然codesandbox.io/s/dark-cherry-06to9 -
@mfeineis - 但是
useState返回一个[state, setter]数组,所以state是否虚假并不重要,该数组永远不会。是的,它会工作,因为|| []从来没有参与过,所以没关系,但是……(你必须仔细观察——也许你已经有了——但那条线是= useState(/*function*/) || [];)
标签: reactjs react-hooks