目标是在映射函数中增加计数,同时跟踪状态中的新值。"Charlie"没有更新,即使在组件的重新渲染和随后的mapData运行中也是如此。同时,每次重新渲染/运行 mapData 都会继续打印"charlie"之外的更新计数。 我的代码大致如下所示:
const [data, setData] = useState([])
const [count, setCount] = useState(0)
const mapData = (apiData) => {
const dataMapped = apiData.map((pic, index) => {
return (
setCount(prevState => (prevState+1))
<div className="charlie">{count}</div>
)
})
setData(prevState => ([...prevState, ...dataMapped]))
}
return {
<div>
<div>{count}</div> {/* shows updated count every render */}
<div>{data}</div> {/* shows 0 every render*/}
</div>
}
这是我两天内第二次看到有人这样做。您需要将更新逻辑与渲染逻辑分开。我强烈建议将JSX存储在状态中,除非这是一些极其罕见的情况。我将在下面评论您的代码,其中包含所有错误:
const [data, setData] = useState([])
const [count, setCount] = useState(0)
const mapData = (apiData) => {
const dataMapped = apiData.map((pic, index) => {
return (
// three things here:
// 1. Never set state from inside a loop because it is going to break the order of hook calls
// 2. Never try to update state during rendering (only do this if you are trying to replicate getDerivedStateFromProps in classes). Add it to useEffect.
// 3. You do not need to calculate the count like this. You can just use index of the array to find the count.
setCount(prevState => (prevState+1))
<div className="charlie">{count}</div>
)
})
// Do not store React elements inside state
setData(prevState => ([...prevState, ...dataMapped]))
}
// this where all your rendering should happen
return {
<div>
<div>{count}</div> {/* shows updated count every render */}
<div>{data}</div> {/* shows 0 every render*/}
</div>
}
这将是我做你正在做的事情的一种方式:
const [data, setData] = useState([])
const populateData = (apiData) => {
setData(prevData => [...prevData, ...apiData]); // just in case I need the internals of the array. You can also map the array here to only store the counts
// if you do not need api data, you can just retrieve the keys, which are the indices of the array
// setData(prevData => [...prevData, ...apiData.keys()]);
}
return (
<div>
<div>{data.length}</div> {/* we already know count from array length */}
<div>{data.map((item, idx) => (
<div className="charlie">{idx + 1}</div> {/* render index to get count */}
))}</div>
</div>
);
首先,你的代码无法编译
我假设您要做的是跟踪呈现的数据量
在这种情况下,您可以将 API 结果的长度添加到计数中
const mapData = (apiData) => {
const dataMapped = apiData.map((pic, index) => {
return (
<div className="charlie">{count}</div>
)
})
setCount(count + dataMapped.length);
setData(prevState => ([...prevState, ...dataMapped]))
}
如果我猜对了,这就是你所追求的,它可以避免循环内的setState
:
const [data, setData] = useState([])
const [count, setCount] = useState(0)
const mapData = (apiData) => {
const dataMapped = apiData.map((pic, index) => {
return (
<div className="charlie">{count + index}</div>
)
})
setCount(prevState => (prevState + apiData.length))
setData(prevState => ([...prevState, ...dataMapped]))
}
return {
<div>
<div>{count}</div> {/* shows updated count every render */}
<div>{data}</div> {/* shows 0 every render*/}
</div>
}