我正在使用useState,它具有2个数组imageList和videoList,然后在useEffect挂钩中,我在数据上使用forEach,然后如果type为image,则将项目推到image。 但是最后我没有得到数组的图像列表或视频列表。
const [list, setDataType] = useState({imageList:[], videoList:[] });
useEffect (()=>{
//data is list of array
dataList.forEach(item =>{
if(!item.images) {
setDataType({...list, imageList:item})
}
else if (item.images[0].type === "video/mp4")
{
setDataType({...list, videoList :item})
}
else if((item.images[0].type === "images/gpeg")
{
setDataType({...list, imageList:item})
}
})
},);
这里的类型检查正常工作,但最后我只获取了最后一个数据,可以是videolist或imageList 最后,我应该获取所有类型为图像的imageList和相同类型为video的相同视频列表的列表
答案 0 :(得分:3)
这不是在循环中调用setState的正确方法。以下是尝试使用数组方法过滤器从功能上构造列表的解决方案。
Foreach ADO Enumerator
答案 1 :(得分:0)
避免在循环内设置状态。在每个setState上,React将重新渲染组件。因此建议先准备您的状态,然后再更新状态。
const [list, setDataType] = useState({imageList:[], videoList:[] });
useEffect (() =>{
let newState = {imageList:[], videoList:[] };
dataList.forEach(item =>{
if(!item.images) {
newState.imageList.push(item);
} else if (item.images[0].type === "video/mp4") {
newState.videoList.push(item);
} else if((item.images[0].type === "images/gpeg") {
newState.imageList.push(item);
}
});
setDataType(prevState => {
return {
imageList: newState.imageList,
videoList: newState.videoList
}
});
},[]);
答案 2 :(得分:0)
理想情况下,您不想在循环内不断调用setState。建立状态,然后进行设置。
在这里两个过滤器可能对您有用。
例如
const [list, setDataType] = useState({imageList:[], videoList:[] });
useEffect (()=>{
//data is list of array
setDataType({
videoList: dataList.filter(item => item.images[0].type === 'video/mp4'),
imageList: dataList.filter(item => item.images[0].type === 'images/gpeg')
});
},);
答案 3 :(得分:0)
请勿使用useEffect
和useState
钩子进行数据转换,这不是异步流的一部分。
使用useMemo
可以更好地处理这种情况。当datalist
发生变化时,useMemo
将产生list
,如果不发生变化,将使用记忆值。此外,它不会导致无限循环,因为在侦听其自身状态时不会引起重新渲染。
要创建list
,请使用可容纳mime类型及其各自类型的Map。减少项目的数组,并根据您从Map中获得的类型,将它们推入images
或videos
子数组中。
/** external code (not in the hook) **/
const types = new Map([['video/mp4', 'video'], ['images/gpeg', 'image']])
const getListType = ({ type }) => types.has(type) ?
`${types.get(type)}List` : null
/** hook code **/
const list = useMemo(() => dataList.reduce((r, item) => {
const list = getListType(item.images[0])
is(list) r[list].push(item)
return r;
}, { imageList:[], videoList:[] }), [dataList])