React传递道具给孩子们

时间:2017-10-28 09:14:59

标签: reactjs

我试图将额外的道具传递给this.props.children,我看到了这个答案how to pass props to children with React.cloneElement?

从某种原因,虽然我没有收到任何错误,但我看不到道具

所以我有这个状态

this.state = {
    open: true
}

我希望将其传递给this.props.children,这是我迄今为止所做的:

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

当我在console.logging this.props对孩子们时,我看不到我的新道具。

---编辑--- 孩子们看起来像这样:

render() {
    console.log(this.props)
    // other code
}

BTW我正在使用react 16.0

2 个答案:

答案 0 :(得分:2)

将道具传递给儿童有两种方式:

儿童作为职能

孩子不是一个React元素,而是一个函数。

调用子功能:

const List = ({ children, sidebarState }) => (
  <ul>
  {
    children(sidebarState)
  }
  </ul>
);

传递孩子的功能:

<List sidebarState={sidebarState}>
  {
    (sidebarState) => (
      <Item sidebarState={sidebarState} />
    )
  }
</List>

工作示例:

const { Component } = React;

const Item = ({ sidebarState }) => (
  <li>{sidebarState ? 'open' : 'close'}</li>
);

const List = ({ children, sidebarState }) => (
  <ul>
  {
    children(sidebarState)
  }
  </ul>
);

class App extends Component {
  constructor(props) {
    super(props);
    
    this.state = {
        sidebarState: true
    }
  }
  
  toggleOpen = () => this.setState((prevState) => ({
    sidebarState: !prevState.sidebarState
  }));
  
  render() {
    const { sidebarState } = this.state;
    
    return (
      <div>
        <button onClick={this.toggleOpen}>Toggle</button>
        
        <List sidebarState={sidebarState}>
          {
            (sidebarState) => (
              <Item sidebarState={sidebarState} />
            )
          }
        </List>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  demo
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="demo"></div>

<强> React.cloneElement

工作示例:

const { Component } = React;

const Item1 = ({ sidebarState }) => (
  <li>{sidebarState ? 'open' : 'close'}</li>
);

const Item2 = ({ sidebarState }) => (
  <li>{sidebarState ? 'open' : 'close'}</li>
);

const List = ({ children, sidebarState }) => (
  <ul>
  {
    React.Children.map(children, (child) => React.cloneElement(child, { sidebarState }))
  }
  </ul>
);

class App extends Component {
  constructor(props) {
    super(props);
    
    this.state = {
        sidebarState: true
    }
  }
  
  toggleOpen = () => this.setState((prevState) => ({
    sidebarState: !prevState.sidebarState
  }));
  
  render() {
    const { sidebarState } = this.state;
    
    return (
      <div>
        <button onClick={this.toggleOpen}>Toggle</button>
        
        <List sidebarState={sidebarState}>
          <Item1 />

          <Item2 />
        </List>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  demo
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="demo"></div>

答案 1 :(得分:0)

这里是一个例子。

之前(不将道具传递到children

    <div className="layout">
      {children}
    </div>

之后(向每个孩子传递额外的props1props2道具):

    <div className="layout">
      {
        React.Children.map(children, (child) => {
          return React.cloneElement(child, {
            props1: 1,
            props2: 2,
          });
        })
      }
    </div>
  

props1props2与每个孩子的现有道具合并。

关于TypeScript类型,您必须使用React.ReactElement而不是React.ReactNode,否则TS编译器会在React.Children.map处抱怨(或ts忽略它):

type Props = {
  children: React.ReactElement;
};

  

有关更多说明,请参见https://medium.com/better-programming/passing-data-to-props-children-in-react-5399baea0356,这对我的理解非常有帮助! (#mediumPaywall)