不使用render。)方法中的React.cloneElement传递道具

安托万C.

我有两个React组件,一个Layout类和一个HomePage类:

HomePage是需要products道具的组件

HomePage.js

import React, { Component } from 'react';

export class HomePage extends Component {
    render() {
        if (!this.props.products) {
            return (<div>Products not loaded yet</div>);
        }
        return (<div>Products loaded!</div>);
    }
}

Layout是一个组件,用于显示来自使用所建立的路线的孩子react-router该班负责将products道具传递给使用React.cloneElement

Layout.js

import React, { Component } from 'react';
import { NavMenu } from './NavMenu';
import { Footer } from './Footer';

export class Layout extends Component {    
    constructor(props) {
      super(props);
      this.state = {
          products: null,
          loading: true
      };
    }    

    // Make an api call when the component is mounted in order to pass
    // additional props to the children
    componentDidMount() {
      this.populateProductsData();
    }

    async populateProductsData() {
      const response = await fetch('api/products/all');
      const data = await response.json();
      this.setState({ products: data, loading: false });    
    }

    render() {
        if (this.state.loading) {
            return (<div>App loading</div>);
        }

        const childrenWithProps = React.Children.map(this.props.children, child => {
            const props = { products: this.state.products };
            if (React.isValidElement(child)) {
                return React.cloneElement(child, props);
            }
            return child;
        });

        return (
          <div>
                <NavMenu />
                {childrenWithProps}
                <Footer />
          </div>
        );
    }
}

路由是在App组件中进行的:

App.js

export default class App extends Component {
  render () {
    return (
        <Layout>
            <Route exact path='/'
                component={HomePage}/>
        </Layout>
    );
  }

因此,我期望

  1. App loading未进行API调用时,在页面上显示消息
  2. Products not loaded yet在道具未传递给Layout孩子时,在页面上显示消息
  3. 在页面上显示Products loaded!消息

但是,该应用程序停留在第二步:products子组件永远不会接收道具。代码将编译,没有运行时错误,并且后端Api被触发并发送有效响应。

为什么product道具render()在子HomePage组件方法中永远不可用


编辑:

按照@Nikita Chayka的回答,应在传递路线时传递道具:

Layout.js

export class Layout extends Component {    
    render() {
        return (
          <div>
                <NavMenu />
                {this.props.children}
                <Footer />
          </div>
        );
  }
}

App.js

export default class App extends Component {
    constructor(props) {
        super(props);

        this.state = {
            products: null,
            loading: true
        };
    }    

    componentDidMount() {
        this.populateProductsData();
    }

    async populateProductsData() {
        const response = await fetch('/api/products/all');
        const data = await response.json();
        this.setState({ products: data, loading: false });    
    }

    render() {
        if (this.state.loading)
            return (<div>App loading</div>);

        return (
        <Layout>
            <Route exact path='/'
                render={(props) => (<HomePage {...props} products={this.state.products}/>)}/>
        </Layout>
    );
  }
}
尼基塔·查卡(Nikita Chayka)

您的Layout组件会将产品属性传递给Route组件,而不是Home组件,基本上,您将拥有

<Route products={} component={Home} path="/" exact/>

但是您需要将其传递给Home,您可以在此处检查想法-https: //ui.dev/react-router-v4-pass-props-to-components/

编辑

您不应将组件属性提供给Route,而应仅提供渲染。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章