tengo este componente:
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> ); } }Quiero que el botón se deshabilite cuando el valor de entrada esté vacío. Pero el código anterior no funciona. Dice:
add-item.component.js:78 TypeError no capturado: no se puede leer la propiedad 'valor' de indefinido
apuntando a disabled={!this.input.value} . ¿Qué puedo estar haciendo mal aquí? Supongo que tal vez la referencia aún no se haya creado cuando se ejecuta el método render . Si, entonces, ¿cuál es la solución?
Usar refs no es una buena práctica porque lee el DOM directamente, es mejor usar el state de React en su lugar. Además, su botón no cambia porque el componente no se vuelve a renderizar y permanece en su estado inicial.
Puede usar setState junto con un detector de eventos onChange para representar el componente nuevamente cada vez que cambia el campo de entrada:
// 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} />Aquí hay un ejemplo de trabajo:
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>En HTML,
<button disabled/> <buttton disabled="true"> <buttton disabled="false"> <buttton disabled="21">Todos ellos se reducen a disabled="true" porque devuelve verdadero para una cadena no vacía. Por lo tanto, para devolver false, pase una cadena vacía en una declaración condicional como 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> ); }Aquí hay una variedad de componentes funcionales que usan ganchos de reacción.
El código de ejemplo que proporcioné debería ser lo suficientemente genérico para modificarlo con el caso de uso específico o para cualquiera que busque "Cómo deshabilitar un botón en React" que llegó aquí.
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;