[英]React Hook useEffect issue with setState
I am using useState which has 2 array imageList and videoList and then in useEffect hook i am using forEach on data then if type is image then push to item to image .我正在使用具有 2 个数组 imageList 和 videoList 的 useState ,然后在 useEffect 钩子中,我在数据上使用 forEach ,然后如果类型是图像,则将项目推送到图像。 But at last i am not getting imagelist or video list of array.
但最后我没有得到数组的图像列表或视频列表。
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})
}
})
},);
Here type check is working correctly but at last i get last fetch data only which can be videolist or imageList In last i should get list of all imageList whose type is image and same video list whose type is video这里类型检查工作正常,但最后我只得到最后一次获取的数据,它可以是 videolist 或 imageList 最后我应该得到所有类型为 image 的 imageList 和类型为 video 的相同视频列表的列表
It is not a proper way to call setState in a loop.在循环中调用 setState 不是正确的方法。 Below is an attempted solution using array method filter to functionally construct the list.
以下是使用数组方法过滤器功能构建列表的尝试解决方案。
const [list, setDataType] = useState({ imageList: [], videoList: [] });
useEffect(() => {
let videos = dataList.filter(item => item.images[0].type === "video/mp4")
let images = dataList.filter(item => item.images[0].type === "images/gpeg")
setDataType({imageList: images, videoList: videos})
}, []);
Avoid set state inside a loop.避免在循环内设置状态。 On each setState, React will re-render the component.
在每个 setState 上,React 将重新渲染组件。 So recommended to prepare your state first and then update the state.
所以建议先准备好状态,然后再更新状态。
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
}
});
},[]);
Ideally you don't want to be calling setState constantly inside your loop.理想情况下,您不希望在循环中不断调用 setState。 Build the state up and then set it.
建立状态,然后设置它。
Two filters might work for you here..两个过滤器可能适合你这里..
eg.例如。
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')
});
},);
Don't use the useEffect
& useState
hooks for data transformation, which is not part of an asynchronous flow.不要使用
useEffect
和useState
挂钩进行数据转换,这不是异步流的一部分。
This case is better handled with useMemo
.使用
useMemo
可以更好地处理这种情况。 When the datalist
changes, useMemo
will produce the list
, and if it doesn't change, the memoized value would be used.当
datalist
变化, useMemo
会产生list
,如果不改变,将要使用的memoized值。 In addition, it won't cause an infinite loop, because it won't cause a rerender while listening to its own state.此外,它不会导致无限循环,因为它在监听自己的状态时不会导致重新渲染。
To create list
, use a Map that will hold the mime-types and their respective types.要创建
list
,请使用一个 Map 来保存 mime-types 及其各自的类型。 Reduce the array of items, and according to the type you get from the Map, push them in the images
or videos
sub-arrays.减少item的数组,并根据你从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])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.