useState触发父组件重渲染导致自定义RadioButton选中CSS动画失效如何解决
解决方案
1. 确保列表渲染的key为稳定唯一值
遍历options渲染RadioButton时,必须给每个子项绑定稳定、唯一不重复的key,直接使用option.id作为key即可,禁止使用数组下标index作为key:
{options.map((option) => ( <Form.RadioButton key={option.id} value={option.id} onChange={setSelectedOption} selected={selectedOption === option.id} > {option.description} </Form.RadioButton> ))}
2. 用React.memo包装子组件跳过不必要重渲染
给RadioButton子组件包裹React.memo,只要传入的props没有发生变化,子组件就不会触发重渲染,也不会被销毁重建:
const RadioButton = React.memo(({ children, value, onChange, selected }: IRadioButtonProps): JSX.Element => { const rootClasses = classNames('RadioButton-root', { 'RadioButton-root-selected': selected }); // 补充缺失的点击事件逻辑 const onClick = () => onChange(value) return ( <RadioButtonContainer className={rootClasses} onClick={onClick}> <div className='RadioButton-icon'> <Done fontSize='inherit' className='RadioButton-icon-check' /> </div> <div className='RadioButton-label'>{children}</div> </RadioButtonContainer> ); })
useState返回的setSelectedOption函数引用是永久稳定的,只要其他props没有变化,memo会正常生效。
3. 排查父组件异常卸载的根因
修改header标题后选中选项会重置标题,说明整个HappyMeterForm组件被卸载后重新挂载了,需要排查外层逻辑:
- 检查是否外层路由、条件渲染逻辑导致HappyMeterForm被销毁重建
- 确认useEffect的依赖数组确实是空数组,避免getHappyMeter重复执行触发question和options的重新赋值
4. 可选:状态拆分降低重渲染范围
如果父组件还有其他复杂状态,可以把选中状态、options等拆分到更小的子组件,或者使用useMemo缓存渲染的选项列表,减少重渲染的影响范围:
const optionNodes = useMemo(() => { return options.map((option) => ( <Form.RadioButton key={option.id} value={option.id} onChange={setSelectedOption} selected={selectedOption === option.id} > {option.description} </Form.RadioButton> )) }, [options, selectedOption]) // 渲染时直接使用缓存的optionNodes <div className='options'> {optionNodes} </div>
注意:不要用普通变量存储需要响应式更新的状态,普通变量变更不会触发React的重渲染逻辑,必须使用useState存储选中状态才能保证视图同步更新。
内容的提问来源于stack exchange,提问作者Lauro
相关产品推荐
相关产品推荐

