2015-10-03 14 views
17

Po kliknięciu tego pola wyboru znacznik wyboru nie znika, mimo że konsola console.log w procedurze onChange wskazuje, że stan został zmieniony na false. Z drugiej strony, gdy stan zmienia się za pomocą osobnego przycisku, znacznik wyboru odpowiednio włącza się i wyłącza.Pole wyboru Reakcja nie przełącza się

export default class TestComponent extends Component { 

constructor(props) { 
    super(props); 
    this.state = { 
     is_checked: true 
    }; 
    this.updateCheckbox = this.updateCheckbox.bind(this); 
    this.pressButton = this.pressButton.bind(this); 
} 
updateCheckbox(event) { 
    event.preventDefault(); 

    this.setState({is_checked: !this.state.is_checked}); 
    console.log(this.state.is_checked); // This logs 'false' meaning the click did cause the state change 
    console.log(event.target.checked); // However, this logs 'true' because the checkmark is still there 

} 
pressButton(event){ 
    event.preventDefault(); 
    this.setState({is_checked: !this.state.is_checked}); 
} 
render(){ 

    return (
    <input type="checkbox" onChange={this.updateCheckbox} checked={this.state.is_checked} ></input> 
    <button onClick={this.pressButton}>change checkbox state using button</button> 
    ); 
} 
} 
+0

wiem, że to było trochę czasu, ale jakoś zaakceptowane odpowiedź jest mylące (choć nie źle). Poza tym myślę, że nie powinieneś rozwiązywać tego problemu z dwukierunkowym wiązaniem, tak jak to robiłeś we własnej odpowiedzi. – ftor

Odpowiedz

20

Myślę, że widzę, co się dzieje.

Po kliknięciu przycisku przełącza się is_checked, który sprawdza lub odznacza pole. Ale to kończy się wyzwalaniem dla pola wyboru, które również przełącza stan ... W rzeczywistości kodowałeś nieskończoną pętlę. Chociaż, ponieważ React partie/debounces setState operacji, twój kod nie zablokuje twojej strony.

Spróbuj tego:

var React = require("react"); 

var Component = React.createClass({ 
    getInitialState: function() { 
     return { 
      isChecked: true 
     }; 
    }, 

    handleCheckboxChange: function(event) { 
     console.log("checkbox changed!", event); 
     this.setState({isChecked: event.target.checked}); 
    }, 

    toggleIsChecked: function() { 
     console.log("toggling isChecked value!"); 
     this.setState({isChecked: !this.state.isChecked}); 
    }, 

    handleButtonClick: function(event) { 
     console.log("button was pressed!", event); 
     this.toggleIsChecked(); 
    }, 

    render: function() { 
     return (
      <div> 
       <input type="checkbox" onChange={this.handleCheckboxChange} checked={this.state.isChecked} /> 
       <button onClick={this.handleButtonClick}>change checkbox state using this button</button> 
      </div> 
     ); 
    } 
}); 

module.exports = Component; 

pamiętać, że można uczynić ten kod nawet czystsze za pomocą Reaguj na valueLink (czytaj więcej tutaj: https://facebook.github.io/react/docs/two-way-binding-helpers.html)

+0

Dzięki za pomoc. Podany kod zawierał ten sam problem, ale przydatne było łącze do dwukierunkowego wiązania. Zaktualizowano mój post, aby pokazać działające rozwiązanie. –

+0

Zapomniałem dodać linię wewnątrz 'handleCheckboxChange', gdzie faktycznie aktualizuje stan' isChecked' - sekret używa wartości 'event.target.checked'. Zaktualizowałem kod, tylko w celach informacyjnych. Oto też skrzypce: https://jsfiddle.net/xqb2mxsq/ – sarink

+1

Możesz to naprawić, usuwając "event.preventDefault();" linia. Ponieważ to uniemożliwia sprawdzenie pola wyboru. zatem zawsze będzie to ten sam stan. –

0

Zmieniono kod za dokumentacji React na dwóch sposób wiązania, które Kabir podał link.

Aby pracować musiałem

  1. użytkowania "React.createClass" zamiast "rozszerza komponent" w celu wykorzystania LinkedStateMixin

    import react from 'react/addons' 
    
    var TestComponent = React.createClass({ 
    mixins: [React.addons.LinkedStateMixin], 
    render: function(){ .... 
    
  2. usuń onChange = 'updateCheckbox' i użyj this.linkState zamiast tego.

    <input type="checkbox" checkedLink={this.linkState(this.state.is_checked)} ></input> 
    
7

Przyczyną tego zachowania ma do czynienia ze szczegółowo realizacji React - a dokładniej sposób, jak reagować normalizuje zmieniają obsługi przeglądarki poprzeczny. W przypadku wejść radiowych i pól wyboru React używa zdarzenia kliknięcia zamiast zdarzenia zmiany. Gdy zastosujesz preventDefault w dołączonej procedurze obsługi zdarzeń, to powstrzyma przeglądarkę od wizualnej aktualizacji wejścia radio/pole wyboru. Istnieją dwa możliwe obejścia:

  • użytku stopPropagation alternatywnie
  • umieścić przełącznik w setTimeout: setTimeout(x => this.setState(x), 0, {is_checked: !this.state.is_checked});

Korzystnie nie używasz preventDefault w ogóle, chyba że jest to absolutnie konieczne.

Zajrzyj do tego React Github issue, aby uzyskać więcej informacji.

+1

pozbycie się preventDefualt naprawiło problem dla mnie, używając reakcji 15 i maszynopisu 2.2 (przepraszam za złe formatowanie) toggleMyCheckbox (checkboxExent: React.ChangeEvent ) { checkboxExent.preventDefault(); this.setState ({ checkboxModel: this.state.checkboxModel, sprawdzone: this.state.checked }) } do .. toggleMyCheckbox (checkboxExent: React.ChangeEvent ) { to. setstate ({ checkboxModel: this.state.checkboxModel, sprawdzone: this.state.checked }) } –

+0

Dziękuję pozbyłem domyślny zapobiec również i pracował dla mnie. –

0

Należy pamiętać, że setstate jest asynchroniczne, więc:

console.log(event.target.checked); 

nie mają odzwierciedlenia zmian natychmiast.Mój sposób obsłużyć kilka pól checkbox:

toggleCheckbox(name, event) { 
    let obj = {}; 
    obj[name] = !this.state[name]; 
    this.setState(obj); 
} 

Pola:

<input type="checkbox" name="active" value={this.state.active} checked={this.state.active} onChange={this.toggleCheckbox.bind(this, 'active')} /> 

<input type="checkbox" name="qtype" value={this.state.qtype} checked={this.state.qtype} onChange={this.toggleCheckbox.bind(this, 'qtype')} />