【问题标题】:How to disable button in React.js如何在 React.js 中禁用按钮
【发布时间】:2017-05-20 05:07:34
【问题描述】:

我有这个组件:

import React from 'react';

export default class AddItem extends React.Component {

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


render() {
    return (
        <div className="add-item">
            <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>
        </div>
    );
}

}

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

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

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

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

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

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

    // 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} />
    

    这是一个工作示例:

    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 (
          <div className="add-item">
            <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>
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <AddItem placeholder="Value" onButtonClick={v => console.log(v)} />,
      document.getElementById('View')
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id='View'></div>

    【讨论】:

    • 这是正确答案!内部状态应该用于更新输入的变化,并且按钮应该简单地检查这一点。 +1
    • this.state 有一个限制,它会再次呈现 UI,因此如果您在子组件中输入文本框并绑定到 onChange 事件,它会失去文本框的焦点。如果它在同一个组件中很好,但在子组件中使用时会失去焦点。
    • @Dynamic 这不应该发生。你有一个可行的例子吗?
    • @Adrianopolis React 会从 DOM 中删除 disabled 属性,如果它设置为 false——这是跨浏览器友好的。
    • @Adrianopolis 我不知道该告诉你什么。使用检查器查看实际运行的演示代码。 React 正在删除 disabled 属性。这是 JSX,而不是 HTML。这里没有问题。
    【解决方案2】:

    在 HTML 中,

    <button disabled/>
    <buttton disabled="true">
    <buttton disabled="false">
    <buttton disabled="21">
    

    所有这些都归结为 disabled="true" 这是因为它为非空字符串返回 true。 因此,为了返回 false,请在条件语句中传递一个空字符串,例如 this.input.value?"true":""

    render() {
        return (
            <div className="add-item">
                <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>
            </div>
        );
    }
    

    【讨论】:

    • 如果 stack-overflow 有支持答案的选项,我会选择这个答案
    • buttton 在这里拼错了吗?
    【解决方案3】:

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

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

    简而言之

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

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

    【讨论】:

      【解决方案4】:

      在 React 中控制组件渲染的典型方法很少。

      但是,我在这里没有使用任何这些,我只是使用 ref 来命名组件的底层子级。

      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 (
                <div className="add-item">
                <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>
                </div>
              );
          }
      }
      
      ReactDOM.render(<AddItem / > , document.getElementById('root'));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
      <div id="root"></div>

      【讨论】:

        【解决方案5】:

        非常简单的解决方案是使用useRef hook

        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启用按钮

        【讨论】:

          【解决方案6】:

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

          来自the React docs on refs,强调我的:

          回调将在组件被挂载或卸载后立即执行

          【讨论】:

            【解决方案7】:

            这是一个使用反应钩子的功能组件。

            我提供的示例代码应该足够通用,可以使用特定用例进行修改,或者任何搜索“如何在 React 中禁用按钮”并登陆此处的人。

            import React, { useState } from "react";
            
            const YourComponent = () => {
              const [isDisabled, setDisabled] = useState(false);
              
              const handleSubmit = () => {
                console.log('Your button was clicked and is now disabled');
                setDisabled(true);
              }
            
              return (
                  <button type="button" onClick={handleSubmit} disabled={isDisabled}>
                    Submit
                  </button>
              );
            }
            
            export default YourComponent;
            

            【讨论】:

              【解决方案8】:

              我也遇到过类似的问题,结果我们不需要钩子来做这些,我们可以进行条件渲染,它仍然可以正常工作。

              <Button
                  type="submit"
                  disabled={
                      name === "" || email === "" || password === "" ? true : false
                  }
                  fullWidth
                  variant="contained"
                  color="primary"
                  className={classes.submit}>
                  SignUP
              </Button>
              

              【讨论】:

              • 很酷的解决方案,我也是这样做的
              • ? true : false 是不必要的,因为=== 已经返回一个布尔值。
              【解决方案9】:

              只需添加:

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

              【讨论】:

                猜你喜欢
                • 2023-01-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-06-02
                • 2019-07-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多