专栏名称: 前端早读课
我们关注前端,产品体验设计,更关注前端同行的成长。 每天清晨五点早读,四万+同行相伴成长。
目录
相关文章推荐
51好读  ›  专栏  ›  前端早读课

【第3516期】避免陷入状态同步的陷阱

前端早读课  · 公众号  · 前端  · 2025-05-26 08:00

正文

请到「今天看啥」查看全文


columns , setColumns ] = useState ( initColumns )
...
}

到了 2026 年,客户的业务拓展到了国际市场,有了新的需求。他们开始收集更多订单属性,比如货币、国家等,同时希望用户可以自定义表格列的显示。你添加了一个设置按钮(⚙)在表头旁边,用户点击后可以选择要显示哪些列。

由于可见列是可变的,不能再写成常量,所以你需要用状态来存储它们。并且这个状态要被多个组件共享(比如 OrdersList 和设置按钮组件),为了避免 props 层层传递,你使用了 React 的 Context(ColumnsCtx)来存储列状态。当然你也可以用 Zustand 、Jotai、Redux 或 URL 参数,原理一样。状态初始化使用默认列数组。

2027 年:筛选功能
function Filters(){
    const [filtersuseContext(FiltersCtx)
    return filters.map(filter=>(
        <Filter filter={filter}/>
    ))
}

function OrdersList(){
    const [columnsuseContext(ColumnsCtx)
    const [filtersuseContext(FiltersCtx)
    const orders useOrders(columns, filters)
    return <Table data={orders}/>
}

 type Filters = Array<{
    attribute: string,
   operator?:'='|'>'|',
   values?: Array<string|number>
 }>

function FiltersProvider(){
    const [filters, setFiltersuseState()
    ...
}

到 2027 年,客户的订单量迅速增长,用户需要按列值来筛选数据。你新增了 Filters 组件,实现筛选功能。跟列一样,筛选项也是动态变化的,无法写死,且需要多个组件访问,因此你用 FiltersCtx 上下文来管理它。

筛选的逻辑是:用户在筛选组件中选择条件(例如客户名为 Ondrej),组件会调用状态更新函数,更新 FiltersCtx 中的值,从而触发 OrdersList 的重新渲染,useOrders hook 会根据新条件重新获取数据。

状态初始化

你尝试运行代码,却发现筛选项不显示。为什么?因为 FiltersCtx 默认是空的。你需要给它一个初始值。

const initColumns =[
    {attribute:






请到「今天看啥」查看全文