Redux Toolkit中Dispatch动作过慢致UI冻结问题排查与求助
勾选清单状态更新导致UI冻结的问题排查与优化建议
核心问题
开发类似Trello的嵌套勾选清单时,创建清单和添加项功能正常,但切换项的完成状态(勾选/取消)时,dispatch更新全局状态的操作过慢,导致UI冻结。曾考虑用异步dispatch解决,不确定是否可行。
相关状态更新代码
Dispatch调用
dispatch( updatecarditem({ checklistId, itemId: index, itemStatus: checked, }), );
Reducer处理逻辑
updatecarditem: (state: any, {payload}) => { const checklistId = payload.checklistId; const itemId = payload.itemId; let item = state.entities[0]?.checklist?.[checklistId]?.checklistItem?.[itemId]; if (payload.itemTitle != undefined) item.itemTitle = payload.itemTitle; if (payload.itemStatus != undefined) item.itemStatus = payload.itemStatus; },
组件结构补充
主清单组件(CheckListItem)
export const CheckListItem: FC<CheckListItemProps> = ({item, index}) => { const card = useSelector<any, any>(cardDetails); const [value, setValue] = useState(item?.checklistTitle); const [newItem, setNewItem] = useState(''); const dispatch = useDispatch(); useEffect(() => { setValue(item?.checklistTitle); }, [item?.checklistTitle]); const toggleVisible = () => { setVisible((prev) => !prev); }; const addCheckistItem = useCallback(() => { if (!newItem.length) { return; } const newCItem = {itemTitle: newItem, itemStatus: false}; updateChecklist([...item?.checklistItem, newCItem]); setNewItem(''); }, [newItem, item?.checklistItem]); const updateChecklist = useCallback( (clitem = item?.checklistItem) => { if (value.length < 3) { showToast( 'error', 'Checklist name should contain atleast 3 characters', ); return; } let newls = [...card?.checklist]; newls[index].checklistTitle = value; newls[index].checklistItem = clitem; dispatch( updatecard({ checklist: newls, }), ); }, [value, card?.checklist], ); return ( <VStack style={styles.cardinfoviews}> <CustomInput onSubmit={updateChecklist} value={value} setValue={setValue} /> <VStack style={styles.cardinfoviews}> {item?.checklistItem?.map((citem: any, itemindex: number) => ( <CheckItem // THIS IS THE NESTED COMPONENT key={itemindex} citem={citem} index={itemindex} checklistId={index} /> ))} <Input onSubmitEditing={addCheckistItem} value={newItem} onChangeText={setNewItem} maxLength={40} variant="underlined" placeholder="Add item..." /> </VStack> ) </VStack> ); };
嵌套项组件(CheckItem)
const CheckItem: FC<CheckItemProps> = ({citem, index, checklistId}) => { const [value, setValue] = useState(citem?.itemTitle); const [checked, setChecked] = useState(citem?.itemStatus); const dispatch = useDispatch(); useEffect(() => { setValue(citem?.itemTitle); }, [citem?.itemTitle]); useEffect(() => { setChecked(citem?.itemStatus); }, [citem?.itemStatus]); const updatecheckItem = useCallback( (checked = citem?.itemStatus) => { setChecked(checked); dispatch( updatecarditem({ checklistId, itemId: index, itemStatus: checked, }), ); }, [checklistId, index], ); const updateItemName = useCallback(() => { if (value.length < 3) { showToast('error', 'Item name should contain atleast 3 characters'); return; } dispatch( updatecarditem({ checklistId, itemId: index, itemTitle: value, }), ); }, [value, index, checklistId]); return ( <Checkbox value={citem?.itemTitle} isChecked={checked} onChange={updatecheckItem}> <Input w="85%" onSubmitEditing={updateItemName} variant="unstyled" value={value} onChangeText={setValue} multiline numberOfLines={1} blurOnSubmit /> </Checkbox> ); };
已定位问题及待优化点
已确认问题源于过多不必要的重渲染,以下是代码中触发重渲染的关键点:
- 主组件
CheckListItem:useSelector直接返回整个card对象,card内任何微小变化都会触发组件重渲染,建议改用精确选择器,仅提取当前清单所需数据。updateChecklist回调依赖card?.checklist,每次checklist变化都会生成新的回调,导致子组件CheckItem频繁接收新props触发重渲染。- 遍历
checklistItem时用itemindex作为key,列表项增删或顺序变化时,React会错误复用组件,引发不必要重渲染,建议改用每个item的唯一ID作为key。
- 嵌套组件
CheckItem:- 同时维护本地状态
value、checked和全局状态,通过useEffect同步会导致额外重渲染,建议直接使用全局状态作为Checkbox和Input的数据源,去掉冗余的本地状态同步。 updatecheckItem回调依赖项未包含citem?.itemStatus,可能捕获旧值;且父组件重渲染时回调引用变化,会触发Checkbox重新渲染。
- 同时维护本地状态
- Reducer逻辑:
- 直接修改
state中的嵌套对象(item.itemStatus = payload.itemStatus),违反Redux不可变性原则,导致React无法正确检测状态变化,引发异常重渲染或更新不及时。需创建嵌套对象副本,修改后替换原对象。
- 直接修改
关于异步dispatch:Redux的dispatch本身是同步的,可通过Thunk或Saga中间件实现异步action,但当前问题核心是重渲染而非异步操作,优先解决重渲染才是关键,异步dispatch无法直接解决UI冻结。
内容的提问来源于stack exchange,提问作者Irfan wani
相关产品推荐
相关产品推荐

