使用 Redux 和 React Hooks,Flatlist 不会 re-render 它里面的各个组件也不会
Using Redux and React Hooks, Flatlist will not re-render nor will the individual components inside of it
我正在使用 React Native、React Hooks、Redux 和 Function 组件。我正在使用 useSelector 从 Redux 的状态中获取一个大数组,然后使用 Flatlist 遍历它。在我的 Flatlist 中,我渲染了多个 child 组件,包括我的 child 的 children。我把主要的 child 粘贴在这个 post 的底部。当我在一个单独的屏幕上并且 FlatList 处于非活动状态并且 属性 在我的数组 trackingBoardList
中的 object 内部发生变化时,我希望当我返回屏幕时 Flatlist 会重新呈现,但事实并非如此。此外,即使我尝试使用 React.memo()
记忆 child 组件 AvatarListItem
,child 本身也不会 re-render。我无法将完整列表获取到 re-render,也无法将 children 单独获取到 re-render。 Flatlist 是否与嵌套 object 的 React Hooks 和数组不兼容?在我的减速器中,当它改变时,我确实不可变地返回那个数组,我正在使用 Immer draft
.
我使用 useSelector 获取我的状态。这是一个大数组,有很多深层嵌套 objects:
const trackingBoardList = useSelector((state: iAppState) => {
return state.trackingBoardAndSchedule.trackingBoardList;
});
我的 Flatlist 是这样的:
<FlatList
data={trackingBoardList}
extraData={trackingBoardList}
keyExtractor={() => uuid()}
renderItem={({ item, index }) => {
return (
<AvatarListItem
patientID={item.patient.id}
patientFirstName={item.patient.name_first}
patientLastName={item.patient.name_last}
patientMiddleName={item.patient.name_middle}
patientSex={item.patient.gender}
patientAge={calculateAge(item.patient.birth_dttm)}
visitReason={item.reason_for_visit}
time={item.created_dttm}
inProgress={false}
patientAvatarURI={item.patient.profile_image_name}
status={item.evisit_status}
/>
);
}}
/>
我的 child 组件如下所示:
const AvatarListItem = (props: iAvatarListItem) => {
return (
<>
<ListItemContainer {...props}>
<Avatar
avatarSize={42}
avatarType='patient'
avatarUserID={props.patientID}
avatarURI={props.patientAvatarURI}
/>
<NameAgeColumn>
<ColumnTitle>
{props.patientFirstName}
{props.patientMiddleName ? ` ${props.patientMiddleName}` : ''}
{` ${props.patientLastName}`}
</ColumnTitle>
<ColumnSmallText>
{props.patientSex === 'M' ? 'Male, ' : ''}
{props.patientSex === 'F' ? 'Female, ' : ''}
{props.patientAge} Years
</ColumnSmallText>
</NameAgeColumn>
<ReasonColumn>
<ColumnTitle>Reason</ColumnTitle>
<ColumnSmallText>{props.visitReason}</ColumnSmallText>
</ReasonColumn>
<LongBadge>
<LongBadgeText>{props.status}</LongBadgeText>
</LongBadge>
</ListItemContainer>
</>
);
};
export default AvatarListItem;
为了回答我自己的问题,我在发布此消息后立即发现了该错误。这是一个可变性问题。我确信我的状态使用 ImmerJS 是不可变的,但是 Immer 没有使用我的 draft
状态,而是以某种方式自动使用我的 baseState,它几乎在整个应用程序的任何地方都有效,但最终在这个特定的屏幕上引起了问题。如果您遇到一个非常奇怪的重新渲染问题,无论您做什么,组件都拒绝重新渲染,我强烈建议您专注于您的减速器并尝试几种不同的方式来返回您的状态。
我正在使用 React Native、React Hooks、Redux 和 Function 组件。我正在使用 useSelector 从 Redux 的状态中获取一个大数组,然后使用 Flatlist 遍历它。在我的 Flatlist 中,我渲染了多个 child 组件,包括我的 child 的 children。我把主要的 child 粘贴在这个 post 的底部。当我在一个单独的屏幕上并且 FlatList 处于非活动状态并且 属性 在我的数组 trackingBoardList
中的 object 内部发生变化时,我希望当我返回屏幕时 Flatlist 会重新呈现,但事实并非如此。此外,即使我尝试使用 React.memo()
记忆 child 组件 AvatarListItem
,child 本身也不会 re-render。我无法将完整列表获取到 re-render,也无法将 children 单独获取到 re-render。 Flatlist 是否与嵌套 object 的 React Hooks 和数组不兼容?在我的减速器中,当它改变时,我确实不可变地返回那个数组,我正在使用 Immer draft
.
我使用 useSelector 获取我的状态。这是一个大数组,有很多深层嵌套 objects:
const trackingBoardList = useSelector((state: iAppState) => {
return state.trackingBoardAndSchedule.trackingBoardList;
});
我的 Flatlist 是这样的:
<FlatList
data={trackingBoardList}
extraData={trackingBoardList}
keyExtractor={() => uuid()}
renderItem={({ item, index }) => {
return (
<AvatarListItem
patientID={item.patient.id}
patientFirstName={item.patient.name_first}
patientLastName={item.patient.name_last}
patientMiddleName={item.patient.name_middle}
patientSex={item.patient.gender}
patientAge={calculateAge(item.patient.birth_dttm)}
visitReason={item.reason_for_visit}
time={item.created_dttm}
inProgress={false}
patientAvatarURI={item.patient.profile_image_name}
status={item.evisit_status}
/>
);
}}
/>
我的 child 组件如下所示:
const AvatarListItem = (props: iAvatarListItem) => {
return (
<>
<ListItemContainer {...props}>
<Avatar
avatarSize={42}
avatarType='patient'
avatarUserID={props.patientID}
avatarURI={props.patientAvatarURI}
/>
<NameAgeColumn>
<ColumnTitle>
{props.patientFirstName}
{props.patientMiddleName ? ` ${props.patientMiddleName}` : ''}
{` ${props.patientLastName}`}
</ColumnTitle>
<ColumnSmallText>
{props.patientSex === 'M' ? 'Male, ' : ''}
{props.patientSex === 'F' ? 'Female, ' : ''}
{props.patientAge} Years
</ColumnSmallText>
</NameAgeColumn>
<ReasonColumn>
<ColumnTitle>Reason</ColumnTitle>
<ColumnSmallText>{props.visitReason}</ColumnSmallText>
</ReasonColumn>
<LongBadge>
<LongBadgeText>{props.status}</LongBadgeText>
</LongBadge>
</ListItemContainer>
</>
);
};
export default AvatarListItem;
为了回答我自己的问题,我在发布此消息后立即发现了该错误。这是一个可变性问题。我确信我的状态使用 ImmerJS 是不可变的,但是 Immer 没有使用我的 draft
状态,而是以某种方式自动使用我的 baseState,它几乎在整个应用程序的任何地方都有效,但最终在这个特定的屏幕上引起了问题。如果您遇到一个非常奇怪的重新渲染问题,无论您做什么,组件都拒绝重新渲染,我强烈建议您专注于您的减速器并尝试几种不同的方式来返回您的状态。