React扩展函数式组件的替代方案:如何复用含useEffect的公共逻辑
解决方案
方案1:自定义Hook(推荐优先级最高)
React 自定义Hook的设计初衷就是复用组件状态逻辑,完全匹配你的需求,不需要组件继承,也无需重复编写useEffect逻辑。
步骤1:封装自定义Hook
import { useSelector } from 'react-redux'; import { useEffect } from 'react'; // 全局只需要定义一次该Hook const useInitProdData = (AHigherOrderComponent) => { // 直接从Redux Store读取需要的参数,无需通过props透传 const country = useSelector(state => state.country); const prodData = useSelector(state => state.prodData); const index = useSelector(state => state.index); useEffect(() => { // 增加数据存在性守卫,避免未加载时抛出错误 if (!country || !prodData?.[index]) return; const [, code] = country.split('-'); const { sampleData, period, indication } = prodData[index]; AHigherOrderComponent(someReadDataFunction(code, sampleData)); AHigherOrderComponent(someReadDataFunction(code, period)); AHigherOrderComponent(someReadDataFunction(code, indication)); }, [country, prodData, index, AHigherOrderComponent]); };
步骤2:嵌套组件内调用
在三个嵌套组件中只需要一行代码即可调用,无需重复写逻辑:
// 以NestedComponent1为例,其余两个组件写法完全一致 import { useInitProdData } from 'xxx'; const NestedComponent1 = ({ highOrder: { AHigherOrderComponent } }) => { // 直接调用自定义Hook,加载时自动执行数据读取逻辑 useInitProdData(AHigherOrderComponent); // 原有组件逻辑保持不变 return <div>{/* 原有内容 */}</div>; }; export default withHighOrder(NestedComponent1);
该方案优势:
- 逻辑仅编写一次,所有嵌套组件直接复用
- 自动获取Redux Store最新值,无需处理props传递链路
- 依赖项声明完整,不存在闭包陷阱
方案2:无渲染逻辑组件(适配你原有组件思路)
如果你更倾向用组件形式实现,可编写不渲染任何UI的纯逻辑组件,直接嵌入嵌套组件的JSX结构即可,不需要在useEffect中调用组件。
步骤1:封装逻辑组件
import { useSelector } from 'react-redux'; import { useEffect } from 'react'; const ProdDataInit = ({ AHigherOrderComponent }) => { const country = useSelector(state => state.country); const prodData = useSelector(state => state.prodData); const index = useSelector(state => state.index); useEffect(() => { if (!country || !prodData?.[index]) return; const [, code] = country.split('-'); const { sampleData, period, indication } = prodData[index]; AHigherOrderComponent(someReadDataFunction(code, sampleData)); AHigherOrderComponent(someReadDataFunction(code, period)); AHigherOrderComponent(someReadDataFunction(code, indication)); }, [country, prodData, index, AHigherOrderComponent]); // 不输出任何UI内容 return null; }; export default ProdDataInit;
步骤2:嵌套组件内引入
// 以NestedComponent1为例 import ProdDataInit from 'xxx'; const NestedComponent1 = ({ highOrder: { AHigherOrderComponent } }) => { return ( <div> {/* 直接插入逻辑组件,加载时自动触发useEffect */} <ProdDataInit AHigherOrderComponent={AHigherOrderComponent} /> {/* 原有组件内容保持不变 */} </div> ); }; export default withHighOrder(NestedComponent1);
补充注意:你原有代码存在两处问题,示例中已修正:
- 错误的重复赋值语法
const sampleData = prodData[index].sampleData = sampleData;改为直接解构取值- 原useEffect依赖项为空数组,会导致闭包问题,已补充完整依赖项
内容的提问来源于stack exchange,提问作者stacky
相关产品推荐
相关产品推荐

