【问题标题】:How to pass Parent props to Children, when rendering using this.props.children() and React.cloneElement?使用 this.props.children() 和 React.cloneElement 进行渲染时,如何将 Parent 道具传递给 Children?
【发布时间】:2021-05-05 18:31:39
【问题描述】:
<CheckboxGroup name="fruits" value={fruits} onChange={this.setFruits}>
    {(cb) => (
      <>
        <label>
          <Checkbox value="apple" /> Apple
        </label>
        <label>
          <Checkbox value="orange" /> Orange
        </label>
        <label>
          <Checkbox value="watermelon" /> Watermelon
        </label>
      </>
    )}
  </CheckboxGroup>

这里是父组件。我想将名称、值和 onChange 传递给孩子们。

class CheckboxGroup extends React.Component {
   constructor(props){
    super(props);
    this.state = {
      value: this.props.value,
      name: this.props.name
    }
  }
  render() {
    const children = React.Children.map(this.props.children(), child => {
      return React.cloneElement(child);
    });
   return(
     <>
      {children}
     </>
   )
  }
  }
  class Checkbox extends React.Component {
 constructor(props){
   super(props);
 }
 render() {
   console.log(this.props);
   return (
     <>
       <input type="checkbox" value="" name=""  />
     </>
   );
 }
}

如何在孩子中获得父母的道具?我使用的是this.props.children() 而不是this.props.children。从父母那里,我尝试过 React.cloneElement(child, {this.props}) 但不起作用。

【问题讨论】:

  • 是否有特定原因需要使用 React.cloneElement?您的示例似乎不需要此 API 提供的任何特殊功能。
  • 嘿@LyndenNoye 我想使用cloneElement,这样我就可以使用''' '''。只需要子组件中的名称和值。有没有其他办法?

标签: reactjs


【解决方案1】:

据我所知,似乎不需要使用 cloneElement API。你应该能够用更简单的东西来完成你所追求的。

我们可以在最顶层提供我们的数据(即水果),并使用数据结构映射每个项目以呈现带有名称、值和 onChange 回调的复选框组件。不需要克隆任何东西,我们的组件没有自己的状态,所以它们可以是简单的函数组件。

const Checkbox = ({ name, value, onChange, isChecked }) => (
  <input
    type="checkbox"
    name={name}
    value={value}
    onChange={onChange}
    checked={isChecked}
  />
)

const CheckboxGroup = ({ name, values, onChange, selectedValues }) => (
  <div>
    {values.map((value, index) => (
      <label key={index}>
        <Checkbox
          {...{ name, value, onChange }}
          isChecked={selectedValues.includes(value)}
        />
        {value}
      </label>
    ))}
  </div>
)

// an example implementation...

const theFruits = ['Banana', 'Apple', 'Orange']

const MyFruitForm = () => {
  const [selectedFruits, setSelectedFruits] = React.useState([])
  const handleChange = (event) =>
    setSelectedFruits((oldFruits) => {
      if (event.target.checked) {
        return [...oldFruits, event.target.value]
      } else {
        return oldFruits.filter((fruit) => fruit !== event.target.value)
      }
    })
  return (
    <CheckboxGroup
      name="fruit-checkboxes"
      values={theFruits}
      onChange={handleChange}
      selectedValues={selectedFruits}
    />
  )
}

ReactDOM.render(<MyFruitForm />, document.getElementById('root'))
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="root"></div>

【讨论】:

  • 正如我在问题中提到的,我想将复选框呈现为父 CheckboxGroup 的子组件。因此我需要使用 cloneElement。非常感谢你,林登的努力。真的很感激。
  • 您不需要使用 cloneElement 来完成 React 中的常见任务,例如将复选框呈现为子组件。我想知道您为什么要通过使用这样的 cloneElement 来混淆您的输入元素将从何处获取其 onChange 处理程序?
  • @LyndenNoye 你可以使用 React.cloneElement 来获得复合组件模式的灵活性。 kentcdodds.com/blog/compound-components-with-react-hooks
猜你喜欢
  • 2019-01-07
  • 2017-11-19
  • 1970-01-01
  • 2019-12-11
  • 2020-04-07
  • 1970-01-01
  • 2017-11-22
相关资源
最近更新 更多