使用 useSelector 钩子关闭重新渲染太多
Too many re-renders with useSelector hook closure
考虑到这个状态,我需要select从中获取一些数据:
const initialState: PlacesStateT = {
activeTicket: null,
routes: {
departure: {
carriageType: 'idle',
extras: {
wifi_price: 0,
linens_price: 0,
},
},
arrival: {
carriageType: 'idle',
extras: {
wifi_price: 0,
linens_price: 0,
},
},
},
};
所以,我想到了两种方法:
第一个:
const useCoaches = (dir: string) => {
const name = mapDirToRoot(dir);
const carType = useAppSelector((state) => state.places.routes[name].carriageType);
const infoT = useAppSelector((state) => {
return state.places.activeTicket.trainsInfo.find((info) => {
return info.routeName === name;
});
});
const coaches = infoT.trainInfo.seatsTrainInfo.filter((coach) => {
return coach.coach.class_type === carType;
});
return coaches;
};
第二个:
const handlerActiveCoaches = (name: string) => (state: RootState) => {
const { carriageType } = state.places.routes[name];
const { activeTicket } = state.places;
const trainInfo = activeTicket.trainsInfo.find((info) => {
return info.routeName === name;
});
return trainInfo.trainInfo.seatsTrainInfo.filter((coach) => {
return coach.coach.class_type === carriageType;
});
};
const useActiveInfo = (dir: string) => {
const routeName = mapDirToRoot(dir);
const selectActiveCoaches = handlerActiveCoaches(routeName);
const coaches = useAppSelector(selectActiveCoaches);
return coaches;
};
最终,如果第一个工作正常,那么第二个在组件中给出了很多无用的重新渲染。我怀疑 selectActiveCoaches 关闭有问题,也许 React 认为这个 selector 在每次重新渲染时都不同,但也许我错了。你能解释一下它是如何工作的吗?
selectActiveCoaches
以 return seatsTrainInfo.filter()
结束。这 always returns 一个新的数组引用,并且 useSelector
将强制您的组件 re-render 每当您的选择器 returns 一个不同的引用上次。因此,在 每个 调度操作之后,您强制组件 re-render:
https://react-redux.js.org/api/hooks#equality-comparisons-and-updates
这里的一个选项是使用 Reselect 将其重写为记忆选择器:
考虑到这个状态,我需要select从中获取一些数据:
const initialState: PlacesStateT = {
activeTicket: null,
routes: {
departure: {
carriageType: 'idle',
extras: {
wifi_price: 0,
linens_price: 0,
},
},
arrival: {
carriageType: 'idle',
extras: {
wifi_price: 0,
linens_price: 0,
},
},
},
};
所以,我想到了两种方法:
第一个:
const useCoaches = (dir: string) => {
const name = mapDirToRoot(dir);
const carType = useAppSelector((state) => state.places.routes[name].carriageType);
const infoT = useAppSelector((state) => {
return state.places.activeTicket.trainsInfo.find((info) => {
return info.routeName === name;
});
});
const coaches = infoT.trainInfo.seatsTrainInfo.filter((coach) => {
return coach.coach.class_type === carType;
});
return coaches;
};
第二个:
const handlerActiveCoaches = (name: string) => (state: RootState) => {
const { carriageType } = state.places.routes[name];
const { activeTicket } = state.places;
const trainInfo = activeTicket.trainsInfo.find((info) => {
return info.routeName === name;
});
return trainInfo.trainInfo.seatsTrainInfo.filter((coach) => {
return coach.coach.class_type === carriageType;
});
};
const useActiveInfo = (dir: string) => {
const routeName = mapDirToRoot(dir);
const selectActiveCoaches = handlerActiveCoaches(routeName);
const coaches = useAppSelector(selectActiveCoaches);
return coaches;
};
最终,如果第一个工作正常,那么第二个在组件中给出了很多无用的重新渲染。我怀疑 selectActiveCoaches 关闭有问题,也许 React 认为这个 selector 在每次重新渲染时都不同,但也许我错了。你能解释一下它是如何工作的吗?
selectActiveCoaches
以 return seatsTrainInfo.filter()
结束。这 always returns 一个新的数组引用,并且 useSelector
将强制您的组件 re-render 每当您的选择器 returns 一个不同的引用上次。因此,在 每个 调度操作之后,您强制组件 re-render:
https://react-redux.js.org/api/hooks#equality-comparisons-and-updates
这里的一个选项是使用 Reselect 将其重写为记忆选择器: