如何使用 this.props.children 将props从父级传递给子级?

IT技术 javascript reactjs react-router
2021-05-26 07:37:11

我在尝试将props传递给 this.props.children 时遇到困难

我有一个组件 MainLayout 并且我想将props传递给 this.props.children 但他的孩子是这样的:

AppRouter.js

export default class AppRouter extends Component {

  render() {

    return (
      <HashRouter>
        <Switch>
          <MainLayout>
            <Route exact path="/" component={PubsList} />
            <Route exact path="/add-pub" component={AddPub} />
            <Route exact path="/add-pub/:id" component={AddPub} />
          </MainLayout>
        </Switch>
      </HashRouter>
    )
  }
}

MainLayout.js :我使用 React.Children 和 React.CloneElement 来传递 props

export default class MainLayout extends Component {

 constructor(props) {
  super(props);
  this.state = {
   foo: "foo"
  };

  render() {

    return (
      <div className="container" >
        <Menu inverted color='teal' fixed="top" style={{ margin: "0", padding: "20px", borderRadius: "0", display: "block" }}>    
          <Link to="/">
            <Header as='h2' content='PandaBar' floated="left" style={{ color: "white", margin: "0" }} />
          </Link>    
        </Menu>    

        <div className="content" style={{ marginTop: "70px", overflow: "hidden" }} >    

          {React.Children.map(this.props.children, child => {
           return React.cloneElement(child, { foo: this.state.foo })
          })}    

        </div>
      </div>
    );
  }
}

但是,一旦我的路线获得props,它看起来像这样:

<HashRouter>
   <Switch>
     <MainLayout>
        <Route exact path="/" component={PubsList} foo="foo"/>
        <Route exact path="/add-pub" component={AddPub} foo="foo"/>
        <Route exact path="/add-pub/:id" component={AddPub} foo="foo"/>
     </MainLayout>
    </Switch>
</HashRouter>

那么,如何使用此配置将我的props foo 传递给我的组件 PubsList 和 AddPub?

2个回答

在示例中fooprop 被传递给错误的组件 ( Route)。

为了传递给路由组件,component应该更改路由属性:

const withFoo = (Comp, foo) => props => <Comp {...props} foo={foo}/>;
...

  render() {

    return (
      ...
      {React.Children.map(this.props.children, route => {
        return React.cloneElement(route, {
          component: withFoo(route.props.component, this.state.foo)
        });
      })}    
      ...
    );
  }

虽然使用Route渲染props作为另一个答案建议可能更直接。

Route 确实提供了一种将自定义props传递给组件的方法,通过使用renderprops而不是componentprops。您将一个函数传递给renderprop,该函数将被调用时使用通常自动传递的相同 props component然后你可以用这些props做任何你想做的事

一个这样的例子(不包括你的 mainLayout 组件)看起来像这样:

<Route render={(routeProps) => (
  <PubsList hello="world" {...routeProps} />
)}/>

因此,使用它,您可以将任意props放在组件上。但是如何让 MainLayout 决定那些额外的props是什么?我认为您需要修改 MainLayout 以拥有自己的渲染props。

render() {
  let children = null;
  if (this.props.render) {
    children = this.props.render({ foo: this.state.foo })
  }

  return (
    <div className="container" >
      <Menu inverted color='teal' fixed="top" style={{ margin: "0", padding: "20px", borderRadius: "0", display: "block" }}>    
        <Link to="/">
          <Header as='h2' content='PandaBar' floated="left" style={{ color: "white", margin: "0" }} />
        </Link>    
      </Menu>    

      <div className="content" style={{ marginTop: "70px", overflow: "hidden" }} >    
        {children}
      </div>
    </div>
  );
}

你会像这样使用它:

<MainLayout render={(layoutProps) => (
  <React.Fragment>
    <Route exact path="/" render={(routeProps) => 
      <PubsList {...layoutProps} {...routeProps} />
    }/>
    <Route exact path="/add-pub" render={(routeProps) => 
      <AddPub {...layoutProps} {...routeProps} />
    }/>
    <Route exact path="/add-pub/:id" render={(routeProps) => 
      <AddPub {...layoutProps} {...routeProps} />
    }/>
  </React.Fragment>
)} />