Як вимкнути кнопку в React.js


84

У мене є цей компонент:

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: Не вдається прочитати значення властивості undefined

вказуючи на disabled={!this.input.value}. Що я тут можу зробити неправильно? Я здогадуюсь, що можливо ref ще не створений при виконанні renderметоду. Якщо так, то в чому проблема?

Відповіді:


110

Використання refs- це не найкраща практика, оскільки воно читає DOM безпосередньо, краще використовувати React's stateзамість цього. Крім того, ваша кнопка не змінюється, оскільки компонент не відтворюється повторно і залишається у своєму початковому стані.

Ви можете використовувати setStateразом із onChangeпрослуховувачем подій повторне відображення компонента щоразу, коли змінюється поле введення:

// 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 має обмеження на те, що він відображає інтерфейс користувача знову, тому, якщо ви вводите текстове поле в дочірній компонент і прив'язані до події onChange, він втрачає фокус із текстового поля. Якщо він знаходиться в одному компоненті, це нормально, але при використанні в дочірньому компоненті він втрачає фокус.
Динамічний

@Dynamic Це не повинно статися. У вас є робочий приклад цього?
Фабіан Шульц,

Тільки FYI, це не зручно для різних браузерів. Багато браузерів все ще трактують наявність відключених як істинні, навіть якщо встановлено як false. Як це буквально просто перевіряє наявність атрибута відключеним. Ви повинні видалити атрибут disabled, щоб бути зручним для різних браузерів.
Адріанополіс

@Adrianopolis React видаляє disabledатрибут із DOM, якщо для нього встановлено значення false- це зручно для різних браузерів.
Фабіан Шульц,

9

У 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>
    );
}

якщо переповнення стека має опцію допоміжної відповіді, я б вибрав цю відповідь
Ферас,

6

Ви не повинні встановлювати значення вводу через посилання.

Погляньте на документацію для контрольованих компонентів форми тут - https://facebook.github.io/react/docs/forms.html#controli-components

Коротко

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

Тоді ви зможете керувати відключеним станом за допомогою disabled={!this.state.value}


4

Існує кілька типових методів, як ми контролюємо візуалізацію компонентів у React. введіть тут опис зображення

Але я не використовував жодного з них тут, я просто використовував посилання для простору імен, що лежить в основі дочірніх компонентів.

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>


2

this.inputне визначено, доки не refбуде викликаний зворотний дзвінок. Спробуйте встановити this.inputдеяке початкове значення у вашому конструкторі.

З документації React щодо посилань , наголос мій:

зворотний виклик буде виконаний відразу після того, як компонент змонтований або демонтований


0

У мене була подібна проблема, виявляється, нам не потрібні гачки, щоб зробити це, ми можемо зробити умовний візуалізацію, і вона все одно буде працювати нормально.

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

0

просто додайте:

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

0

дуже просте рішення для цього - використання useRefгачка

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.