小能豆

Reactjs:如何从父级修改动态子组件状态或道具?

javascript

我本质上是在尝试制作反应中的标签,但是遇到了一些问题。

这是文件page.jsx

<RadioGroup>
    <Button title="A" />
    <Button title="B" />
</RadioGroup>

当您点击按钮 A 时,RadioGroup 组件需要取消选择按钮 B

“选定”仅表示来自某个状态或属性的类名

这里是RadioGroup.jsx

module.exports = React.createClass({

    onChange: function( e ) {
        // How to modify children properties here???
    },

    render: function() {
        return (<div onChange={this.onChange}>
            {this.props.children}
        </div>);
    }

});

来源Button.jsx并不重要,它有一个常规的 HTML 单选按钮,可以触发原生 DOMonChange事件

预期流量为:

  • 点击按钮“A”
  • 按钮“A”触发 onChange,即原生 DOM 事件,并冒泡至 RadioGroup
  • RadioGroup onChange 监听器被调用
  • RadioGroup 需要取消选择按钮 B。这是我的问题。

这是我遇到的主要问题:我无法将<Button>s 移入RadioGroup,因为其结构使得子元素是任意的。也就是说,标记可以是

<RadioGroup>
    <Button title="A" />
    <Button title="B" />
</RadioGroup>

或者

<RadioGroup>
    <OtherThing title="A" />
    <OtherThing title="B" />
</RadioGroup>

我尝试了一些方法。

尝试:RadioGrouponChange 处理程序中:

React.Children.forEach( this.props.children, function( child ) {

    // Set the selected state of each child to be if the underlying <input>
    // value matches the child's value

    child.setState({ selected: child.props.value === e.target.value });

});

问题:

Invalid access to component property "setState" on exports at the top
level. See react-warning-descriptors . Use a static method
instead: <exports />.type.setState(...)

尝试:RadioGrouponChange 处理程序中:

React.Children.forEach( this.props.children, function( child ) {

    child.props.selected = child.props.value === e.target.value;

});

问题:什么都没有发生,即使我给了Button类一个componentWillReceiveProps方法


尝试:我尝试将父级的某些特定状态传递给子级,这样我就可以只更新父级状态并让子级自动响应。在 RadioGroup 的 render 函数中:

React.Children.forEach( this.props.children, function( item ) {
    this.transferPropsTo( item );
}, this);

问题:

Failed to make request: Error: Invariant Violation: exports: You can't call
transferPropsTo() on a component that you don't own, exports. This usually
means you are calling transferPropsTo() on a component passed in as props
or children.

糟糕的解决方案 #1:使用 react-addons.js cloneWithProps方法在渲染时克隆子项,RadioGroup以便能够向它们传递属性

糟糕的解决方案 #2:围绕 HTML / JSX 实现抽象,以便我可以动态传递属性(杀了我吧):

<RadioGroup items=[
    { type: Button, title: 'A' },
    { type: Button, title: 'B' }
]; />

然后RadioGroup动态构建这些按钮。


阅读 67

收藏
2024-06-12

共1个答案

小能豆

您面临的挑战涉及 React 中组件之间的通信,父组件需要根据某些事件更新其子组件的状态。由于 React 遵循单向数据流,因此无法直接从父组件修改子组件的状态。

但是,您可以通过将状态提升到父组件来实现此行为,父组件会保存状态并将其作为 props 传递给子组件。当子组件中发生事件时,它会通过回调函数通知父组件,然后父组件会相应地更新其状态,然后将状态传递回子组件。

您可以通过以下方式重构组件以实现所需的行为:

  1. 提升状态:将确定选定按钮的状态从RadioGroup组件移动到其父级(Page在本例中为组件)。
  2. 将状态作为道具传递:将选定的状态传递给Button组件。
  3. 处理选择改变:当单击按钮时,通知父组件(Page)有关选择改变的信息。
  4. 更新状态:相应地更新父组件中的状态并将其传递回组件Button

让我们将以下步骤应用到您的代码中:

劉貉复制代码// Button.jsx
class Button extends React.Component {
  render() {
    const { title, selected, onClick } = this.props;
    return (
      <button className={selected ? 'selected' : ''} onClick={onClick}>
        {title}
      </button>
    );
  }
}

// RadioGroup.jsx
class RadioGroup extends React.Component {
  render() {
    const { buttons, onButtonClick } = this.props;
    return (
      <div>
        {buttons.map((button) => (
          <Button
            key={button.title}
            title={button.title}
            selected={button.selected}
            onClick={() => onButtonClick(button.title)}
          />
        ))}
      </div>
    );
  }
}

// Page.jsx
class Page extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      buttons: [
        { title: 'A', selected: false },
        { title: 'B', selected: false },
      ],
    };
    this.handleButtonClick = this.handleButtonClick.bind(this);
  }

  handleButtonClick(selectedTitle) {
    const updatedButtons = this.state.buttons.map((button) => ({
      ...button,
      selected: button.title === selectedTitle,
    }));
    this.setState({ buttons: updatedButtons });
  }

  render() {
    return (
      <div>
        <RadioGroup buttons={this.state.buttons} onButtonClick={this.handleButtonClick} />
      </div>
    );
  }
}

在此设置中:

  • 每个组件都以 prop 的形式Button接收其状态。selected
  • 当单击按钮时,它会调用onButtonClickPage组件传递的处理程序,从而更新组件中的状态Page
  • 然后将更新的状态传回给组件Button,并使用正确的选择状态重新渲染它们。

这种方法允许您维持按钮的选定状态,同时保持组件解耦并遵循 React 的单向数据流。

2024-06-12