React中使用useState和URL参数加载页面如何避免FlatList重复渲染
首先修正你代码中的基础笔误:你将两个副作用钩子错误写为了useState,实际应当使用useEffect。
你遇到的重复渲染问题核心原因如下:
- 组件初始化时
filters默认值为null,会触发第一次列表数据计算,渲染全量内容 - 组件挂载后执行路由参数解析的副作用,哪怕解析得到的
filterParams仍为null,调用setFilters也会触发组件重渲染,进而触发第二次列表数据计算
方案1:直接初始化filters(推荐,适配当前场景)
React Navigation的props.route.params在组件初始化阶段即可直接读取,无需等待挂载后的副作用执行,你可以直接将参数解析逻辑放到useState的初始值回调中,从根源避免二次赋值:
const Foo = (props: any) => { const [filters, setFilters] = React.useState<any | null>(() => { // 初始化阶段直接解析参数,无需后续调用setFilters if(props.route.params.filters){ try { return JSON.parse(props.route.params.filters) } catch(e){} } return null }); // 列表数据完全由filters派生,使用useMemo计算即可,无需额外维护state const items = React.useMemo(() => { return createItemsFromFilters(filters); }, [filters]); return ( <FlatList data={items} //... 其余配置 /> ) }
该方案全程仅触发一次列表数据计算,无多余重渲染,逻辑更简洁。
方案2:添加初始化完成标记(适配filters异步获取场景)
如果你的filters需要异步获取(比如依赖接口返回的过滤参数),无法在初始化阶段拿到,可以新增一个ref标记初始化状态,避免初始null值触发多余更新:
const Foo = (props: any) => { const [items, setItems] = React.useState<any[]>([]); const [filters, setFilters] = React.useState<any | null>(null); // 标记filters是否完成首次初始化 const isFiltersInited = React.useRef(false); React.useEffect(() => { let filterParams: any | null = null; if(props.route.params.filters){ try { filterParams = JSON.parse(props.route.params.filters) } catch(e){} } setFilters(filterParams) isFiltersInited.current = true; }, []); React.useEffect(() => { // 等待初始化完成后再执行列表更新逻辑 if(!isFiltersInited.current) return; const temp = createItemsFromFilters(filters); setItems(temp); }, [filters]); return ( <FlatList data={items} //... 其余配置 /> ) }
内容的提问来源于stack exchange,提问作者pbuzz007
相关产品推荐
相关产品推荐

