简体   繁体   English

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

[英]Calling a Higher-Order Component within Component render

Something simple is tripping up my logic here:一些简单的事情在这里绊倒了我的逻辑:

I have a HOC AnimateOnLoad which renders a default content (used within react-router ) within the page component.我有一个 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>
      )}
   />
);

The animateONLoad HOC looks like this: 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>
         );
      }
   };

However, I am getting an error:但是,我收到一个错误:

Functions are not valid as a React child.函数作为 React 子元素无效。 This may happen if you return a Component instead of from render.如果您返回 Component 而不是从 render 返回,则可能会发生这种情况。 Or maybe you meant to call this function rather than return it.或者,您可能打算调用此函数而不是返回它。

which doesn't make sense to me as I am returning a Component from AnimateOnLoad() ;这对我来说没有意义,因为我从AnimateOnLoad()返回一个Component

Thank you.谢谢你。

Root cause of your error is this你的错误的根本原因是这个

This may happen if you return a Component instead of <Component />如果您返回 Component 而不是 <Component />,则可能会发生这种情况

@ShubhamKhatri Answer will resolve your issue. @ShubhamKhatri Answer 将解决您的问题。 I want to expand his answer.我想扩大他的回答。

Don't Use HOCs Inside the render Method不要在渲染方法中使用 HOC

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. React 的 diffing 算法(称为 reconciliation)使用组件标识来确定它是应该更新现有的子树还是丢弃它并安装一个新的子树。 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.如果从 render 返回的组件与从前一个 render 返回的组件相同(===),React 通过将它与新的比较递归地更新子树。 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 />;
}

Notice how HOC is used outside render in his answer.请注意在他的回答中如何在渲染之外使用 HOC。

The problem here isn't just about performance — remounting a component causes the state of that component and all of its children to be lost.这里的问题不仅仅与性能有关——重新挂载组件会导致该组件及其所有子组件的状态丢失。

That's why its very important to apply HOCs outside the component definition so that the resulting component is created only once.这就是为什么在组件定义之外应用 HOC 非常重要,这样生成的组件只创建一次。 Then, its identity will be consistent across renders.然后,它的身份将在渲染中保持一致。 This is usually what you want, anyway.无论如何,这通常是您想要的。

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

You aren't using the AnimateOnLoad HOC correctly.您没有正确使用AnimateOnLoad HOC。 You need to use it like你需要像这样使用它

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>
      )}
   />
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM