【问题标题】:Next JS Layout component, pass props to childrenNext JS Layout 组件,将 props 传递给 children
【发布时间】:2020-06-12 21:14:04
【问题描述】:

我找到了一个代码,可以解决我在 Next JS re rendering when changed pages 中遇到的问题。但现在我需要向子组件发送道具。我不知道如何让它在这里工作,这是我的 layout.js 代码。如您所见,我可以将道具发送到 Header 组件,但对于孩子我不知道如何,因为它是一个变量而不是一个组件。

import Header from "../components/header";
import Footer from "../components/footer";
import { Fragment } from "react";

export default function Layout({ children, ...pageProps }) {
  return (
    <Fragment>
      <Header
        isRegisterPage={pageProps.isRegisterPage}
        isLoginPage={pageProps.isLoginPage}
        outHome={pageProps.outHome}
      />
      {children}
      <Footer />
    </Fragment>
  );
}

感谢您的帮助

【问题讨论】:

  • 这是 redux(本质上是用漂亮的开发工具反应上下文)大放异彩的东西——维护一个全局状态变量,任何想要的组件都使用它(通过反应上下文和useSelector)使用它,而不是道具钻孔。

标签: javascript reactjs next.js


【解决方案1】:

你考虑过使用 React 的 Context API 吗?这个想法是,当使用 Context API 时,组件的状态会被提升,以便在全球范围内进行管理。如果一个组件需要一个道具,而不是手动向下传递道具(道具钻孔),您可以简单地将您的组件包装在所谓的上下文提供者中。这将允许该组件访问您的应用程序的全局状态。这很好,因为当您的应用程序变得更大时,您可能需要通过许多组件向下传递道具,这可能会造成混乱并增加不必要的混乱。

React 提供了一些很棒的文档来设置您的 React 应用程序以使用 Context API。强烈推荐去看看!

https://reactjs.org/docs/context.html

【讨论】:

    【解决方案2】:

    你可以使用 React 的 cloneElement 来实现。

    React.cloneElement(children, {
        isRegisterPage: pageProps.isRegisterPage,
        isLoginPage: pageProps.isLoginPage,
        outHome: pageProps.outHome
    })
    

    您的案例中的完整示例:

    import Header from "../components/header";
    import Footer from "../components/footer";
    import React, { Fragment } from "react";
    
    export default function Layout({ children, ...pageProps }) {
      return (
        <Fragment>
          <Header
            isRegisterPage={pageProps.isRegisterPage}
            isLoginPage={pageProps.isLoginPage}
            outHome={pageProps.outHome}
          />
          {
              React.cloneElement(children, {
                  isRegisterPage: pageProps.isRegisterPage,
                  isLoginPage: pageProps.isLoginPage,
                  outHome: pageProps.outHome
              })
          }
          <Footer />
        </Fragment>
      );
    }
    

    【讨论】:

      【解决方案3】:

      试试这个

      import Header from "../components/header";
      import Footer from "../components/footer";
      import { Fragment } from "react";
      
      export default function Layout({ children, ...pageProps }) {
      
        function recursiveMap(children, fn) {
          return React.Children.map(children, child => {
            if (!React.isValidElement(child) || typeof child.type == 'string') {
              return child;
            }
        
            if (child.props.children) {
              child = React.cloneElement(child, {
                children: recursiveMap(child.props.children, fn)
              });
            }
        
            return fn(child);
          });
        }
      
        // Add props to all child elements.
        const childrenWithProps = recursiveMap(children, child => {
          // Checking isValidElement is the safe way and avoids a TS error too.
          if (isValidElement(child)) {
            // Pass additional props here
            return cloneElement(child, { currentUser: { ...user } })
          }
      
          return child;
        });
      
        return (
          <Fragment>
            <Header
              isRegisterPage={pageProps.isRegisterPage}
              isLoginPage={pageProps.isLoginPage}
              outHome={pageProps.outHome}
            />
            {childrenWithProps}
            <Footer />
          </Fragment>
        );
      }
      

      【讨论】:

      • 嘿,Akshit,欢迎来到 Stack Overflow!为这个问题提供解决方案的良好开端,但也尝试解释为什么该解决方案有效,以便 Joangel 和其他阅读您的答案的人也能理解该解决方案。这对于没有完全相同的代码但有类似问题的其他人特别有用。
      猜你喜欢
      • 2023-01-11
      • 2021-12-25
      • 1970-01-01
      • 2019-08-09
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      相关资源
      最近更新 更多