遍历子组件,并将每个组件渲染为高阶组件

时间:2019-11-19 11:04:33

标签: javascript reactjs

在将父元素的子元素包装到更高阶组件中然后进行渲染时,我目前遇到问题。

请考虑以下结构:

return (
<div className="App">
  <FocusProvider>
    <TestComponent testProp={'Foo'}/>
    <TestComponent testProp={'Foo'}/>
    <TestComponent testProp={'Foo'}/>
  </FocusProvider>
</div>
);

其中FocusProvider是父元素,TestComponent是子元素,需要包装在一个更高阶的组件中,该组件为其提供生命周期方法并注入道具。

然后称为hoc的高阶组件将覆盖TestComponent的prop,并为其提供生命周期方法,如下所示:

const hoc = (WrappedComponent, prop) => {
  return class extends React.Component {
   shouldComponentUpdate = (prevProps, prop) => {
     return !prevProps === prop
   }
   render(){
     return <WrappedComponent testProp={prop}/>
   }
 }
}

FocusProvider的呈现方法如下:

 render(){
  return(
   this.props.children.map(child => {
    let Elem = hoc(child, 'bar')
    return <Elem/>
  })
 ) 
}

当我尝试渲染时,我得到Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

当我尝试将其更改为:

render(){
  return(
    this.props.children.map(child => {
       let elem = hoc(child, 'bar')
       return elem
    })
  ) 
 }

渲染未返回任何内容。我很困惑,因为我可以直接渲染chil组件,但不能渲染HOC中包装的子组件:

 render(){
  return(
    this.props.children.map(child => {
       return child  //This works
    })
  ) 
 }

我想避免使用React.cloneElement,因为我不想每次父级更新时都通过克隆子元素来触发重新渲染。

任何帮助将不胜感激

1 个答案:

答案 0 :(得分:1)

hoc是一个返回Component而不是jsx的函数。您不能将children包裹在HOC中。

但是您可以只包装FocusProvider并使用cloneElement将道具传递给孩子。这样使用cloneElement不会有问题。实际上是common pattern

function App() {
  return (
    <div className="App">
      <FocusProvider bar="baz">
        <Child />
        <Child />
        <Child />
      </FocusProvider>
    </div>
  );
}

const withHOC = Component => props => {
  return <Component foo="bar" {...props} />;
};

const FocusProvider = withHOC(({ children, foo, bar }) => {
  return React.Children.map(children, child => {
    return React.cloneElement(child, { foo, bar });
  });
});

const Child = ({ foo, bar }) => (
  <>
    {foo}
    {bar}
  </>
);

Edit great-kowalevski-96wum