React.js - 将props从 hoc 传递给孩子

IT技术 javascript reactjs react-router react-router-dom
2021-05-15 12:28:23

我一直试图将一些props从我的 HOC 传递给孩子们。HOC 包装react-router开关和路由。子组件中缺少props。我使用 React.CloneElement 将props添加到孩子,但似乎不起作用

<BrowserRouter>
<Layout>
        <React.Suspense fallback={loading()}>
          <Switch>
            <Route exact path="/" component={Login} />
            <Route path="/dashboard" component={Home} />
            <Route path="/tickets" component={Tickets} />

          </Switch>
        </React.Suspense>
      </Layout>
    </BrowserRouter>

这是 HOC(布局)

class Layout extends React.Component {
   .....

    render() {
        const children = this.props.children && React.cloneElement(this.props.children, { data: 'ok' })
...

子组件没有得到数据props,我只得到这个

{history: {…}, location: {…}, match: {…}, staticContext: undefined}
3个回答

一个工作 HOC 示例,将一个dataprop 注入到基础组件中。

/* HOC */
const withData = Base => () => <Base data="ok" />

/* Component */
class Router extends React.Component {
  render() {
    return this.props.data;
  }
}
 
const RouterWithData = withData(Router); // export default withData(Router);

ReactDOM.render(<RouterWithData />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

this.props.children元素/组件集合所以,你必须map在调用之前cloneElement

return React.Children.map(this.props.children, el => (
    React.cloneElement(el, { data: 'ok' });
); 

使用 HOC,您可以将props传递给直接儿童。

如果您需要将 props 传递给更深层次的孩子,您可能需要使用React Context API

例如 :

// LayoutContext.js
import React from 'react';

/**
 * Create and initialize a context for the Layout component
 */
export default React.createContext({
    data: null,
});
// Layout.js
import React from 'react';
import LayoutContext from './LayoutContext';

/**
 * The Layout component which injects the context
 * All children can consume the context
 */
export default function Layout({ children }) {
    // This is where you set your data
    const data = 'my-value';

    return (
        <LayoutContext.Provider value={{ data }}>
            {children}
        </LayoutContext.Provider>
    );
}
// SomeChild.js
import React from 'react';

/**
 * How you can consume the context in any child declared in the Layout component
 * Here we are using the `useContext` hook but it works the same by using a Consumer
 */
export default function SomeChild() {
    const { data } = React.useContext(LayoutContext);

    // Do whatever you want with the data
}
// App.js
import React from 'react';
import Layout from './Layout';

export default function App() {
    return (
        <BrowserRouter>
            <Layout>
                {/* Any component in this tree can use the LayoutContext */}
            </Layout>
        </BrowserRouter>
    );
}