在Component render中调用高阶组件

时间:2018-07-23 17:00:58

标签: javascript reactjs react-router-v4 higher-order-functions higher-order-components

简单的事情在这里破坏了我的逻辑:

我有一个HOC AnimateOnLoad,它在页面组件中呈现默认内容(在react-router中使用)。

const DefaultLayout = ({ component: Component, ...rest }) => (

   <Route
      {...rest}
      render={matchProps => (
         <div className="page-container">
            {AnimateOnLoad(
               <div className="container">
                  <Head />
                  <Nav />
                  <Component {...matchProps} />
               </div>
            )}
            <Footer />
         </div>
      )}
   />
);

animateONLoad HOC如下:

const AnimateOnLoad = WrappedComponent =>
   class Animator extends Component {
      constructor(props) {
         super(props);
         this.ele = React.createRef();
      }
      componentDidMount() {
         Kute.fromTo(
            this.ele.current,
            { opacity: 0.3 },
            { opacity: 1, duration: 120 }
         ).start();
      }
      render() {
         return (
            <div className="animator" ref={this.ele}>
               <WrappedComponent {...this.props} />
            </div>
         );
      }
   };

但是,我收到一个错误:Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.,这对我来说没有意义,因为我是从AnimateOnLoad()返回Component

谢谢。

2 个答案:

答案 0 :(得分:3)

您没有正确使用AnimateOnLoad HOC。您需要像这样使用它

const CustomComp = (matchProps) => (
     <div className="container">
          <Head />
          <Nav />
          <Component {...matchProps} />
     </div>
);

const HOCComponent = AnimateOnLoad(CustomComp)


const DefaultLayout = ({ component: Component, ...rest }) => (

   <Route
      {...rest}
      render={matchProps => (
         <div className="page-container">
            <HOCComponent {...matchProps}/>
            <Footer />
         </div>
      )}
   />
);

答案 1 :(得分:3)

您的错误的根本原因是

  

如果您返回一个Component而不是

@ShubhamKhatri Answer将解决您的问题。我想扩大他的答案。

  

不要在渲染方法内使用HOC

     

反应的差异算法(称为对帐)使用组件   标识以确定是否应更新现有子树或   扔掉并安装新的。如果组件从   渲染与上一个渲染中的组件相同(===),   React通过将子树与新树进行比较来递归更新子树。   如果它们不相等,则先前的子树将完全卸载。

render() {
  // A new version of Animate is created on every render
  // Animate1 !== Animate2
  const Animate = AnimateOnLoad(MyComponent);
  // That causes the entire subtree to unmount/remount each time!
  return <Animate />;
}

在他的答案中注意如何在渲染外使用HOC。

问题不仅仅在于性能-重新安装组件会导致该组件及其所有子组件的状态丢失。

这就是为什么在组件定义之外应用HOC如此重要,以使生成的组件仅创建一次非常重要的原因。然后,其身份在渲染之间将保持一致。无论如何,通常这就是您想要的。

参考:https://reactjs.org/docs/higher-order-components.html#dont-use-hocs-inside-the-render-method