React Architecture:我有一个通用的中间组件,需要渲染自定义子组件

React Architecture: I have a common middle component that needs to render custom child components

我正在制作一个使用通用网格组件的仪表板。网格有自己独立的功能,并用于应用程序的其他区域。它需要在每个网格项中渲染一个自定义组件,并且有一个活动组件也渲染一个自定义组件,这些自定义组件使用来自 Grids 父组件的函数,无论渲染它是什么,下面是我目前的做法,但我'我很确定有更好的方法。

渲染网格并向下传递组件和功能的父组件

import Grid from './common/grid'

class dashboard extends Component {

gridItemSpecificFunction() { console.log('success') }
activeFunction() { console.log('success again') }

  render() {

   return <Grid 
             CustomComponent={ CustomComponent }
             ActiveComponent={ ActiveComponent }
             activeFunctions={ {activeFunction} }
             gridItemFunctions={ { gridItemSpecificFunction:this.gridItemSpecificFunction } }
 />

  }

}

根据传递的数据呈现自定义活动和网格项目的网格

class Grid extends Component {

render() {

   const {CustomComponent} = this.props

   return (

     <GridWrapper>
       { this.props.dynamicData.map( data => (
       <GridItemWrapper>
         <CustomComponent { ...data } functions={ this.props.gridItemFunctions } />
       </GridItemWrapper>
       ) )

     { active && < ActiveComponent { ...activeData } 
                     functions={ this.props.activeFunctions }/> }

     </GridWrapper>
       }

   )

  }

}

使用通过网格项传递的函数的自定义组件示例

class CustomComponent extends Component {

render() {

   const {gridItemSpecificFunction} = this.props.functions

   return (

     <div onClick={ gridItemSpecificFunction }>
      { this.props.text }
     <div>
       }

   )

  }

}

你真的做得很好,当然还有另一种方法可以做到这一点,可能更好只是因为更容易修改,所以你可能应该使用 Context hook 来完成这个,所以很棒的包基于它们在 Context API Hook,所以一个很好的方法就是这个

import React, { useContext, createContext, useMemo } from 'react';

const FunctionalityContext = createContext({}); // just leave it as empty state

// create a hook that return the context function
const useGridFunctions = () => {
  const functions = useContext(FunctionalityContext);
  return functions;
};

const CustomComponent = () => {
  const functions = useGridFunctions();

  return (
    <div>
      <button onClick={functions.gridItemSpecificFunction}>I am a custom component</button>
    </div>
  );
}

const ActiveComponent = () => {
  const functions = useGridFunctions();

  return (
    <div>
      <button onClick={functions.activeFunction}>I am a active component</button>
    </div>
  );
}

const ParentGrid = ({ functions }) => {
  const functions = useMemo(() => functions, [functions]);
  // the pass functions object to our context provider to get accesso through dom tree
  return (
    <FunctionalityContext.Provider value={functions}>
      <Grid
        CustomComponent={CustomComponent}
        ActiveComponent={ActiveComponent}
      />
    </FunctionalityContext.Provider>
  );
}

如您所见,您仍然保持代码几乎相同,但您添加了一个额外的层来存储组件将使用的功能,因此 Context Api 将帮助您实现这一目标随心所欲