javascript - 如何正确设置子组件和父组件的状态?

标签 javascript reactjs

在下面的示例中,我尝试执行以下操作:

  • 我有输入字段,我想以以下形式捕获对对象中这些输入所做的更改:{ id: value, id: value, ...etc },我可以然后将此数据结构发送到服务来执行...无论什么:)

我在实现时遇到问题:

  • Input组件的输入字段发生变化时,我需要通过setState管理onChange,这是React中的典型做法。但是,我还需要捕获对输入字段所做的更改。
  • 为了捕获更改,我使用组件来处理回调函数,该函数将使用新更改更新状态。
  • 此外,我只允许用户在存在新更改的情况下提交更改。现在保持简单,当存在新更改时启用一个按钮。

TLDR:我认为我使用的设置状态有问题,我试图通过回调函数在子级和父级中设置状态。然而,一个优先于另一个,两个设置状态都不会执行。这是为什么?如何正确实现?

注意:这是伪代码,请原谅任何拼写错误,我尽力保持真实。

  • 提交组件
class Submit extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        const { showButton } = this.props;

        return (
            <button type='button' disabled={!showButton}>
                Hello world!
            </button>
        );
    }

);
  • 输入组件
class Input extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            name: ''
        };
    }

    handleChange = (e) => {
        const { enable } = this.props;
        const id = e.target.id;
        const value = e.target.value;

        this.setState({
            [id]: value
        });

        enable(id, value); // <- Using this here breaks set state.
    }

    render() {
        const { myName } = this.state;

        return (
            <div>
                <input type='text' id='name' onChange={this.handleChange} placeholder='' />
                <input type='text' id='address' onChange={this.handleChange} placeholder='' />
                <!-- there can be more input fields -->
            </div>
        );
    }
}
  • 父组件
class Parent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            enableButton: false,
            inputFieldValues: {},
        };
    }

    enable = (value) => {
        const { inputFieldValue } = this.state;
        let changes = inputFieldValues || {};

        changes[key] = value;

        this.setState({
            enableButton: true,
            inputFieldValues: changes
        });
    }

    render() {
        const { enableButton } = this.state;

        return (
            <div>
                <Input enable={this.enable} />
                <Submit enableButton={enableButton} />
            </div>
        );
    }
}

最佳答案

我不太确定我是否理解了你的问题,但这里是你的伪代码的固定示例。

我注意到的:

const { inputFieldValue } = this.state;
let changes = inputFieldValues || {};

changes[key] = value;

我不知道你是否在真实的应用程序中犯了同样的错误,但我想提一下,这是一个非常粗鲁的错误,可能会导致意外的行为,因为你改变了状态对象,而不是创建新的状态对象。 React 会比较对象引用,但不会对它们进行深入检查。 这个let changes = inputFieldValues || {};应该是let changes = { ...inputFieldValues } || {}; .

此外,您没有为输入提供字段值。虽然它不会影响状态更改,但输入和状态可能会变得不同步。

class Submit extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { enableButton } = this.props;

    return (
      <button type="button" disabled={!enableButton}>
        Hello world!
      </button>
    );
  }
}

class Input extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      name: "",
      address: ""
    };
  }

  handleChange = e => {
    const { enable } = this.props;
    const id = e.target.id;
    const value = e.target.value;

    this.setState({
      [id]: value
    });

    enable(id, value);
  };

  render() {
    const { myName } = this.state;

    console.log("Input:", this.state);

    return (
      <div>
        <input
          type="text"
          id="name"
          onChange={this.handleChange}
          placeholder=""
          {/* Always provide state values to your inputs to make sure they're always synchronized */}
          value={this.state.name}
        />
        <input
          type="text"
          id="address"
          onChange={this.handleChange}
          placeholder=""
          value={this.state.address}
        />
      </div>
    );
  }
}

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      enableButton: false,
      inputFieldValues: {}
    };
  }

  enable = (key, value) => {
    const { inputFieldValues } = this.state;
    // Copy objects, when you change their fields.
    let changes = { ...inputFieldValues } || {};

    changes[key] = value;

    this.setState({
      enableButton: true,
      inputFieldValues: changes
    });
  };

  render() {
    const { enableButton } = this.state;

    console.log("Parent:", this.state);

    return (
      <div>
        <Input enable={this.enable} />
        <Submit enableButton={enableButton} />
      </div>
    );
  }
}

ReactDOM.render(<Parent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

关于javascript - 如何正确设置子组件和父组件的状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54409899/

相关文章:

javascript - 关于react中函数类型的解释

javascript - 未处理的拒绝(类型错误): this is undefined when write this. setState(数据);在 componentDidMount 函数中

javascript - this.state 不会按预期更新

JavaScript/DOM - "CSS Selector"和属性之间有区别吗?

javascript - InvokeScript() 方法返回 null

javascript - Angular 1 : How to wait for promise to resolve in parent controller?

reactjs - 我如何在 React 测试库的单元测试中使用 i18n

node.js - 我遇到了这个错误!本地运行 npm start 时出现代码 ELIFECYCLE 错误?

javascript - 为什么 JavaScript 被称为客户端技术?

javascript - 我可以做什么来存储类的实例并在 react 应用程序的上下文中管理状态