Как отключить кнопку в React.js
У меня есть этот компонент:
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
. Если, так что же это за труд?
Ответы
Ответ 1
Использование refs
не является лучшей практикой, потому что оно напрямую считывает DOM, вместо этого лучше использовать state
React. Кроме того, ваша кнопка не изменяется, потому что компонент не перерисовывается и остается в исходном состоянии.
Вы можете использовать setState
вместе с onChange
событий onChange
чтобы визуализировать компонент каждый раз при изменении поля ввода:
// Input field listens to change, updates React 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>
Ответ 2
Вы не должны устанавливать значение входа через ref.
Взгляните на документацию для компонентов контролируемой формы здесь - 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}
Ответ 3
this.input
не определено до вызова обратного вызова ref
. Попробуйте установить this.input
на некоторое начальное значение в вашем конструкторе.
Из документов React по refs основное внимание уделяется:
обратный вызов будет выполняться сразу после установки или размонтирования компонента
Ответ 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>