2017-01-05 8 views
8

Mam ten komponent:Jak wyłączyć przycisk w 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> 
    ); 
} 

} 

chcę przycisk jest wyłączony, gdy wartość wejściowa jest pusta. Ale powyższy kod nie działa. Jest napisane:

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

wskazując na disabled={!this.input.value}. Co mogę tu robić źle? Zgaduję, że być może ref nie jest jeszcze utworzony, gdy jest wykonywana metoda render. Jeśli tak, to czym jest obejście?

Odpowiedz

18

Korzystanie refs nie jest najlepsza praktyka, ponieważ odczytuje DOM bezpośrednio, to lepiej użyć Reaguj na state zamiast. Ponadto przycisk nie zmienia się, ponieważ komponent nie jest ponownie renderowany i pozostaje w stanie początkowym.

Można użyć setState wraz ze słuchaczem onChange zdarzeń do renderowania komponentu ponownie za każdym razem zmienia się pole wprowadzania:

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

Oto przykład praca:

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>

+0

To jest poprawna odpowiedź! Aby zaktualizować dane wejściowe, należy użyć stanu wewnętrznego, a przycisk powinien się po prostu sprawdzić. +1 –

+0

this.state ma ograniczenie, że ponownie renderuje interfejs, więc jeśli piszesz w polu tekstowym w elemencie potomnym i jesteś powiązany z zdarzeniem onChange, traci ono ostrość z pola tekstowego. Jeśli jest w tym samym komponencie, jest w porządku, ale gdy jest używany w komponencie potomnym, traci skupienie. – Dynamic

+0

@Dynamic To nie powinno się zdarzyć. Czy masz działający tego przykład? –

2

Nie powinieneś ustawiać wartości wejścia poprzez refs.

Spójrz na dokumentacji dla komponentów sterowanych formularza tutaj - https://facebook.github.io/react/docs/forms.html#controlled-components

w pigułce

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

Wtedy będziesz w stanie kontrolować stan disabled za pomocą disabled={!this.state.value}

1

this.input jest niezdefiniowane do wywołania funkcji zwrotnej ref. Spróbuj ustawić this.input na pewną wartość początkową w swoim konstruktorze.

Od the React docs on refs, podkr:

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

0

Istnieje kilka typowych metod sterowania komponentami renderowania Reagować. enter image description here

Ale, nie użyłem żadnego z nich tutaj, po prostu użyłem ref do przestrzeni nazw leżących u podstaw dzieci do komponentu.

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>

Powiązane problemy