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

时间:2019-05-31 09:30:32

标签: javascript reactjs react-router react-router-dom

我一直在尝试将一些道具从我的HOC传递给孩子们。 HOC包装响应路由器的交换机和路由。子组件中缺少道具。我使用React.CloneElement将道具添加到孩子中,但似乎不起作用

<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' })
...

子组件没有得到数据道具,我只是得到了

{history: {…}, location: {…}, match: {…}, staticContext: undefined}

3 个答案:

答案 0 :(得分:4)

一个有效的HOC示例鞭子将一个data道具注入到基础组件中。

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

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>

答案 1 :(得分:0)

this.props.children是元素/组件的集合。因此,您必须map才能调用cloneElement

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

答案 2 :(得分:0)

使用HOC,您可以将道具传递给直接的孩子。

如果您需要将道具传递给较深的孩子,则可能需要使用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>
    );
}