React函数式导航组件如何给单个元素添加active类并解决渲染滞后问题
问题根源
你遇到的渲染滞后问题本质是React state异步批量更新导致的:同一事件处理函数内多次调用setState时,读取的都是当前渲染周期的旧state值,连续两次更新stateOptions时使用的都是未更新的旧数组,同时刚调用SetCurrentOption后立刻读取currentOption拿到的也是更新前的旧值,才会出现两步延迟的现象,不需要额外引入useEffect解决,优化状态更新逻辑即可。
最优解决方案
你可以完全去掉冗余的currentOption状态,同时利用事件对象的currentTarget属性直接获取绑定点击事件的按钮元素,不需要额外判断子元素标签处理冒泡逻辑,一次性完成状态更新,代码如下:
import { options } from 'somewhere...' import { useState } from 'react' export default function SideMenu(props){ const [stateOptions, setStateOptions] = useState([...options]) function activeOption(e){ // currentTarget永远指向绑定了onClick事件的button元素,无需处理子元素冒泡 const targetId = e.currentTarget.id // 一次性生成新的选项数组,仅更新对应项的激活状态 const newOptions = stateOptions.map(item => ({ ...item, activity: item.id === targetId })) setStateOptions(newOptions) } return( <aside className={styles.sideDiv}> <nav> {stateOptions.map(({id, img, name, activity, link}) => { return( <button key={id} id={id} onClick={activeOption} className={activity ? styles.active : ""}> <Image src={img}/> <p className={timeColor.theme}> {name} </p> </button> ) })} </nav> </aside> ) }
更简化的实现
如果你的导航项不会动态增删,不需要在选项数组里存储activity属性,单独存一个激活项id即可,性能更高逻辑更清晰:
import { options } from 'somewhere...' import { useState } from 'react' export default function SideMenu(props){ // 初始值可根据需求设置为第一个选项的id或空值 const [activeId, setActiveId] = useState(options[0]?.id || '') function activeOption(e){ setActiveId(e.currentTarget.id) } return( <aside className={styles.sideDiv}> <nav> {options.map(({id, img, name, link}) => { return( <button key={id} id={id} onClick={activeOption} className={id === activeId ? styles.active : ""}> <Image src={img}/> <p className={timeColor.theme}> {name} </p> </button> ) })} </nav> </aside> ) }
内容的提问来源于stack exchange,提问作者Cristian Diaz
相关产品推荐
相关产品推荐

