简体   繁体   English

Next JS Layout 组件,将 props 传递给 children

[英]Next JS Layout component, pass props to children

I have found a code that solved my problem in Next JS re rendering when changing pages.我在更改页面时找到了解决我在 Next JS 重新渲染中的问题的代码。 But now i need to send props to the children component.但现在我需要向子组件发送道具。 I got no idea how i can make it works here, this is my layout.js code.我不知道如何让它在这里工作,这是我的 layout.js 代码。 As you can see i can send props to Header component but for children i dont know how, because it is a variable and not a component.如您所见,我可以将道具发送到 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>
  );
}

Thank you for the help感谢您的帮助

Have you considered using React's Context API?你考虑过使用 React 的 Context API 吗? The idea is that when using the Context API your component's state get's lifted, to be managed at a global scale.这个想法是,当使用 Context API 时,组件的状态会被提升,以便在全球范围内进行管理。 If a component needs a prop, instead of passing props down manually (prop drilling) you can simply wrap you component in what's known as a context provider.如果一个组件需要一个道具,而不是手动向下传递道具(道具钻探),您可以简单地将您的组件包装在所谓的上下文提供者中。 This will allow that Component to access the global state of your application.这将允许该组件访问您的应用程序的全局状态。 This is good because, when your application gets bigger, you may need to pass props down through many components which can clutter and add unneeded confusion.这很好,因为当您的应用程序变得更大时,您可能需要通过许多组件向下传递道具,这可能会造成混乱并增加不必要的混乱。

React provides some great documentation to set your React application up to use the Context API. React 提供了一些很棒的文档来设置你的 React 应用程序以使用 Context API。 Highly recommend checking it out!强烈建议检查一下!

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

Try this尝试这个

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

You can use React's cloneElement to achieve that.你可以使用 React 的cloneElement来实现。

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

Complete example in your case:您的案例中的完整示例:

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

From the answer of Lucas Raza, below is an example that uses Context API to apply themes to different components根据 Lucas Raza 的回答,下面是一个使用 Context API 将主题应用于不同组件的示例

1.Create a context File 1.创建上下文文件

//ThemeContex.js
import { createContext, useState } from "react";

export const ThemeContext = createContext();

export const withThemeContext = Component => {
    const WrappedComp = props => {
  
        const [darkColor,lightColor] = ["#3b3b3b", "#ddd"]
        const [lightBackgoround,darkBackgoround] = ["#ececec","#1d2a35"]       

        const darkTheme = {
            backgroundColor: darkBackgoround,
            color:lightColor,
        }

        const lightTheme = {
            backgroundColor: lightBackgoround,
            color:darkColor,
        }

        const themes = {
            darkTheme, lightTheme
        }
    
        const [theme, setTheme] = useState(lightTheme)

    
        const children ={
            theme,
            themes, 
            setTheme,
        }
    
        return(
            <StylesContext.Provider value={{...children}} >
                <Component {...props} />    
            </StylesContext.Provider>
        )
    }
    
    return WrappedComp;
}
  1. In _app.js, import withThemeContext higher component and wrap MyApp with it when exporting it.在 _app.js 中,导入 withThemeContext 更高的组件,并在导出时用它包装 MyApp。

     import { withThemeContext } from '../components' function MyApp({ Component, pageProps }) { return <Component {...pageProps} /> } export default withThemeContext(MyApp)
  2. You can know use theme any where in a component您可以知道在组件中的任何位置使用主题

     import { useContext } from 'react' import {ThemeContext} from '../components' export default function Home() { const { theme } =useContext(ThemeContext) return ( <div id="home" style={theme}> // Home logic... </div> ) }

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

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