【问题标题】:How can I pass props from a Parent to Child with this.props.children?如何使用 this.props.children 将道具从父母传递给孩子?
【发布时间】:2018-09-27 12:42:00
【问题描述】:

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

我有一个组件 MainLayout,我想将道具传递给 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>
    );
  }
}

但是,一旦我的路线得到了道具,它就会变成这样:

<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 ?

【问题讨论】:

  • 你可以尝试使用render方法作为&lt;Route exact path="/" render={(props) =&gt; &lt;PubsList {...props} /&gt;} /&gt;
  • 这个问题以前被欺骗了。这个问题stackoverflow.com/questions/22639534/… 是相关的,但解决了一个不同的问题。虽然它的答案可以给出一些想法,但它们并不能直接回答这个问题。

标签: javascript reactjs react-router


【解决方案1】:

在示例中,foo 属性传递给了错误的组件 (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 =>”是什么意思?我知道它用于从原始组件中获取道具,但是如果不简化此功能,它是如何编写的?非常感谢
  • 不客气。它是高阶组件,reactjs.org/docs/higher-order-components.html。其中props =&gt; ... 是功能组件,reactjs.org/docs/…withFoo 为路由组件创建一个包装器,其工作方式与它类似,但另外提供了 foo 属性。
【解决方案2】:

Route 确实提供了一种将自定义 props 传递给组件的方法,即使用 render prop 而不是 component prop。您将一个函数传递给render 属性,该函数将使用与使用component 时通常自动传递的相同属性进行调用。然后你可以用这些道具做任何你想做的事

一个例子(不包括你的 mainLayout 组件)如下所示:

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

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

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>
)} />

【讨论】:

  • 谢谢,这对我了解发生了什么很有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 2018-02-07
相关资源
最近更新 更多