使用逻辑运算符有条件地启用/禁用按钮元素

时间:2019-02-14 02:14:13

标签: javascript reactjs button

这是ReactJS的新手。搜索类似的主题无济于事。在我的应用上,我只想在所有字段都包含内容的情况下启用提交按钮。所有输入字段均已绑定状态。

在我的onChange事件处理函数上:

  • 我更新绑定到我的字段的状态,从而更新我的输入字段
  • 在同一个处理函数中,我基于需要使用'&&'的每个状态的逻辑运算符链声明一个布尔值
  • 将!result分配给名为'buttonDisabled'的状态
  • 然后将此状态分配给按钮的“禁用”属性
  • 禁用属性的默认状态为true

代码

onInputChange = (e) => {
    e.preventDefault();
    const newValue = e.target.value;

    const targetElement = e.target.id;
    this.setState(() => {

        return {
            entryInput: newValue, 
            [targetElement]: newValue
        }
    })

    this.setState( () => {
        let buttonState =
        (this.state.symbol && 
        this.state.contracts &&
        this.state.open);
        return {
            buttonDisabled: buttonState
        }

    })

}

在我的按钮元素上:

<Button disabled={this.state.buttonDisabled} onClick={...} ?>

预期结果-禁用“提交”,直到所有状态都包含值(即所有字段都包含值)

实际结果-“提交”被禁用,但是在我填写的最后一个文本框的第二个条目上启用。

  • 我已经控制台记录了生成的布尔值,并且它与确切条件匹配
  • 启用/禁用按钮似乎是在进行更新
  • 我认为可能是&&返回布尔值/值的方式,因此我明确地使用了===的比较和相同的问题。还尝试了if / else语句

我可能在逻辑上有些差距,但是我一直在转动方向盘,希望能得到一些帮助。

谢谢

2 个答案:

答案 0 :(得分:1)

您不需要将值存储在状态中,您实际上可以在 render 函数本身中进行检查。默认情况下,每次 setState 调用时,都会调用 render 函数:

import React from "react";
import ReactDOM from "react-dom";

class Form extends React.Component {
  constructor() {
    super();
    this.state = {
      name: "",
      age: ""
    };
  }

  nameChange = (e) => {
    this.setState({ name: e.target.value });
  };

  ageChange = (e) => {
    this.setState({ age: e.target.value });
  };

  submit = () => {
    const { name, age } = this.state;
    alert(`name: ${name} is age: ${age}`);
  };

  render() {
    const { name, age } = this.state;
    const enabled = name.length > 0 && age.length > 0;
    return (
      <form onSubmit={this.submit}>
        <input
          type="text"
          placeholder="Enter name"
          value={this.state.name}
          onChange={this.nameChange}
        />
        <input
          type="text"
          placeholder="Enter age"
          value={this.state.age}
          onChange={this.ageChange}
        />
        <button disabled={!enabled}>Submit</button>
      </form>
    );
  }
}

const root = document.getElementById("root");
ReactDOM.render(<Form />, root);

此外,请记住:

  

setState()不会立即使this.state突变,而是创建一个   等待状态转换。调用此后访问this.state   方法可能会返回现有值。没有   保证对setState的调用的同步操作,并且调用可以   进行批量处理以提高性能。

答案 1 :(得分:0)

我认为您需要更改第二个setState,以便您接受状态作为输入参数:

this.setState((newState) => {
    let buttonState =
    (newState.symbol && 
    newState.contracts &&
    newState.open);
    return {
        buttonDisabled: buttonState
    }
})

通常,如果您在setState updater fn内部使用状态,则需要使用作为参数传递给updater而不是this.state的状态。

我相信这是因为不能保证对setState的调用是立即进行的,并且在多次调用的情况下,可以将它们排队并分批应用。换句话说,在您的情况下,更新仅在fns运行后才应用于this.state,因此,如果您依赖this.state,则第二个setState updater fn将不会看到第一个setState的效果updater fn。如果第二个fn需要访问第一个fn的结果,则需要使用提供的中间状态值。

本教程的“将函数传递给setState()”一节对此进行了更好的解释:https://css-tricks.com/understanding-react-setstate/#article-header-id-1

以及此处的官方文档:https://reactjs.org/docs/react-component.html#setstate。文档中的这句话很关键:

  

将setState()视为请求而不是立即命令来更新组件。为了获得更好的感知性能,React可能会延迟它,然后在一次通过中更新几个组件。 React不能保证状态更改会立即应用。

希望这会有所帮助。