关于javascript:如何在React.js中禁用按钮

How to disable button in React.js

我有这个组成部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React from 'react';

export default class AddItem extends React.Component {

add() {
    this.props.onButtonClick(this.input.value);
    this.input.value = '';
}


render() {
    return (
       
            <input type="text" className="add-item__input" ref={(input) => this.input = input} placeholder={this.props.placeholder} />
            <button disabled={!this.input.value} className="add-item__button" onClick={this.add.bind(this)}>Add</button>
       
    );
}

}

我希望在输入值为空时禁用按钮。 但是上面的代码不起作用。 它说:

add-item.component.js:78 Uncaught TypeError: Cannot read property 'value' of undefined

指向disabled={!this.input.value}。 我在这里怎么做错了? 我猜测执行render方法时可能尚未创建ref。 如果可以,那么解决方法是什么?


使用refs并不是最佳实践,因为它直接读取DOM,最好使用React的state。同样,您的按钮不会更改,因为该组件不会重新渲染并保持其初始状态。

您可以将setStateonChange事件侦听器一起使用,以在每次输入字段更改时再次呈现组件:

1
2
3
4
5
// Input field listens to change, updates React's state and re-renders the component.
<input onChange={e => this.setState({ value: e.target.value })} value={this.state.value} />

// Button is disabled when input state is empty.
<button disabled={!this.state.value} />

这是一个工作示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class AddItem extends React.Component {
  constructor() {
    super();
    this.state = { value: '' };
    this.onChange = this.onChange.bind(this);
    this.add = this.add.bind(this);
  }

  add() {
    this.props.onButtonClick(this.state.value);
    this.setState({ value: '' });
  }

  onChange(e) {
    this.setState({ value: e.target.value });
  }

  render() {
    return (
     
        <input
          type="text"
          className="add-item__input"
          value={this.state.value}
          onChange={this.onChange}
          placeholder={this.props.placeholder}
        />
        <button
          disabled={!this.state.value}
          className="add-item__button"
          onClick={this.add}
        >
          Add
        </button>
     
    );
  }
}

ReactDOM.render(
  <AddItem placeholder="Value" onButtonClick={v => console.log(v)} />,
  document.getElementById('View')
);
1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js">


在HTML中,

1
2
3
4
<button disabled/>
<buttton disabled="true">
<buttton disabled="false">
<buttton disabled="21">

它们全部归结为disabled =" true",这是因为它为非空字符串返回true。
因此,为了返回false,请在诸如this.input.value?" true":"之类的条件语句中传递一个空字符串。

1
2
3
4
5
6
7
8
render() {
    return (
       
            <input type="text" className="add-item__input" ref={(input) => this.input = input} placeholder={this.props.placeholder} />
            <button disabled={this.input.value?"true":""} className="add-item__button" onClick={this.add.bind(this)}>Add</button>
       
    );
}


您不应该通过ref设置输入的值。

在这里查看受控表单组件的文档-https://facebook.github.io/react/docs/forms.html#受控组件

简而言之

1
<input value={this.state.value} onChange={(e) => this.setState({value: e.target.value})} />

然后,您可以使用disabled={!this.state.value}来控制禁用状态


在React中,我们如何控制组件渲染的典型方法很少。
enter image description here

但是,我在这里没有使用任何这些,我只是使用了ref来对组件的子元素进行命名空间命名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class AddItem extends React.Component {
    change(e) {
      if ("" != e.target.value) {
        this.button.disabled = false;
      } else {
        this.button.disabled = true;
      }
    }

    add(e) {
      console.log(this.input.value);
      this.input.value = '';
      this.button.disabled = true;
    }

    render() {
        return (
         
          <input type="text" className ="add-item__input" ref = {(input) => this.input=input} onChange = {this.change.bind(this)} />
         
          <button className="add-item__button"
          onClick= {this.add.bind(this)}
          ref={(button) => this.button=button}>Add
          </button>
         
        );
    }
}

ReactDOM.render(<AddItem / > , document.getElementById('root'));
1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js">


在调用ref回调之前,this.input是不确定的。尝试在构造函数中将this.input设置为某个初始值。

从引用的React文档中,重点是:

the callback will be executed immediately after the component is mounted or unmounted


为此,非常简单的解决方案是使用useRef挂钩

1
2
3
4
5
6
7
8
9
10
11
12
13
const buttonRef = useRef();

const disableButton = () =>{
  buttonRef.current.disabled = true; // this disables the button
 }

<button
className="btn btn-primary mt-2"
ref={buttonRef}
onClick={disableButton}
>
    Add
</button>

同样,您可以使用buttonRef.current.disabled = false启用按钮


只需添加:

1
<button disabled={this.input.value?"true":""} className="add-item__button" onClick={this.add.bind(this)}>Add</button>

我有一个类似的问题,原来我们不需要钩子来做这些,我们可以进行条件渲染,它仍然可以正常工作。

1
2
3
4
5
6
7
8
9
10
11
<Button
    type="submit"
    disabled={
        name ==="" || email ==="" || password ==="" ? true : false
    }
    fullWidth
    variant="contained"
    color="primary"
    className={classes.submit}>
    SignUP
</Button>