【问题标题】:React.js - passing props to children from hocReact.js - 将道具从 hoc 传递给孩子
【发布时间】:2019-10-16 22:38:35
【问题描述】:

我一直在尝试将一些道具从我的 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' })
...

子组件没有得到 data 道具,我得到了这个

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

【问题讨论】:

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


    【解决方案1】:

    一个有效的 HOC 示例,将 data 属性注入到基础组件中。

    /* 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>

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        使用 HOC,您可以将 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>
            );
        }
        

        【讨论】:

          猜你喜欢
          • 2018-08-25
          • 2020-08-08
          • 2017-10-03
          • 1970-01-01
          • 1970-01-01
          • 2018-04-09
          • 2016-03-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多