在组件渲染中调用高阶组件

Calling a Higher-Order Component within Component render

一些简单的事情让我的逻辑在这里被绊倒:

我有一个 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 from render. Or maybe you meant to call this function rather than return it.

这对我来说没有意义,因为我要从 AnimateOnLoad();

返回 Component

谢谢。

您没有正确使用 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>
      )}
   />
);

你错误的根本原因是这个

This may happen if you return a Component instead of <Component />

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

Don’t Use HOCs Inside the render Method

React’s diffing algorithm (called reconciliation) uses component identity to determine whether it should update the existing subtree or throw it away and mount a new one. If the component returned from render is identical (===) to the component from the previous render, React recursively updates the subtree by diffing it with the new one. If they’re not equal, the previous subtree is unmounted completely.

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