React如何解决复用公共组件时重复传递props的冗余问题
解决方案
方案1:使用React Context注入公共依赖(最适配当前场景)
你用到的user、cartValue、fetchproductResults都属于跨组件复用的公共逻辑,用Context封装后,LandingHeader内部可以直接消费依赖,不需要每个父组件重复传参。
首先创建Context配置文件:
// LandingHeaderContext.js import { createContext, useContext, useState } from 'react'; const LandingHeaderContext = createContext(); // 封装Provider组件,所有公共逻辑统一在这里维护 export function LandingHeaderProvider({ children, allproducts }) { const [word, setWord] = useState(''); const [result, setResult] = useState(allproducts); // user、cartValue如果有其他全局数据源也可以直接接入,不需要在这里重新声明 const [user, setUser] = useState(null); const [cartValue, setCartValue] = useState(0); const fetchproductResults = (keyword) => { setWord(keyword); if (keyword !== "") { const searchedRs = allproducts.filter((eachproduct) => { return Object.values(eachproduct) .join("") .toLowerCase() .includes(keyword.toLowerCase()); }); setResult(searchedRs); } else { setResult(allproducts); } }; return ( <LandingHeaderContext.Provider value={{ fetchproductResults, user, cartValue, word, result }}> {children} </LandingHeaderContext.Provider> ); } // 封装消费Hook,简化组件调用逻辑 export function useLandingHeader() { return useContext(LandingHeaderContext); }
在应用根组件(如App.js)用Provider包裹所有需要用到LandingHeader的页面:
import { LandingHeaderProvider } from './LandingHeaderContext'; import Landing from './Landing'; import Cart from './Cart'; function App({ allproducts }) { return ( <LandingHeaderProvider allproducts={allproducts}> <Landing /> <Cart /> {/* 其他路由/业务组件 */} </LandingHeaderProvider> ); }
修改LandingHeader组件,内部直接消费Context,不需要再接收外部props:
// landingHeader.js import { useLandingHeader } from './LandingHeaderContext'; export default function LandingHeader() { const { fetchproductResults, user, cartValue } = useLandingHeader(); // 原有组件逻辑直接复用上面三个变量即可,不需要改动 }
之后所有页面使用时不需要传任何参数:
// Cart.js 直接使用即可,不需要额外修改逻辑 import { Fragment } from "react"; import Landingheader from "./landingHeader"; const Cart = () => { return ( <Fragment> <Landingheader /> </Fragment> ); } export default Cart;
方案2:抽离自定义Hook复用逻辑(不需要全局状态的场景)
如果不想引入全局Context,可以把LandingHeader需要的所有依赖逻辑抽成自定义Hook,两个父组件直接调用Hook获取参数即可,不需要重复写逻辑:
// useLandingHeaderProps.js import { useState } from 'react'; export default function useLandingHeaderProps(allproducts, user, cartValue) { const [word, setWord] = useState(''); const [result, setResult] = useState(allproducts); const fetchproductResults = (keyword) => { setWord(keyword); if (keyword !== "") { const searchedRs = allproducts.filter((eachproduct) => { return Object.values(eachproduct) .join("") .toLowerCase() .includes(keyword.toLowerCase()); }); setResult(searchedRs); } else { setResult(allproducts); } }; return { fetchproductResults, user, cartValue, word, result } }
父组件调用示例:
// Landing.js 用法 import useLandingHeaderProps from './useLandingHeaderProps'; function Landing({ allproducts, user, cartValue }) { const headerProps = useLandingHeaderProps(allproducts, user, cartValue); return <div> <Landingheader {...headerProps} /> </div> }
// Cart.js 用法 import { Fragment } from "react"; import Landingheader from "./landingHeader"; import useLandingHeaderProps from './useLandingHeaderProps'; const Cart = ({ allproducts, user, cartValue }) => { const headerProps = useLandingHeaderProps(allproducts, user, cartValue); return ( <Fragment> <Landingheader {...headerProps} /> </Fragment> ); } export default Cart;
方案3:封装通用包装组件
如果需要进一步简化调用,可以直接封装一个自带参数的LandingHeader包装组件,后续所有页面统一使用这个封装后的组件即可:
// CommonLandingHeader.js import Landingheader from './landingHeader'; import useLandingHeaderProps from './useLandingHeaderProps'; export default function CommonLandingHeader() { // 这里接入你的商品、用户、购物车数据源即可 const allproducts = []; const user = {}; const cartValue = 0; const headerProps = useLandingHeaderProps(allproducts, user, cartValue); return <Landingheader {...headerProps} /> }
内容的提问来源于stack exchange,提问作者node Dev
相关产品推荐
相关产品推荐

