2016-06-15 16 views
6

Mam metodę handleSelection wywoływaną po kliknięciu przycisku, jednak jeśli kliknę przycisk, gdy stan nie zostanie ustawiony, gdy dojdzie do this.setState({selectedFoods: newSelections});. Cała reszta metody jest wykonywana poprawnie (jak informują mnie moje różne pliki console.logs :)). Gdy przycisk zostanie kliknięty po raz drugi, wszystko w metodzie zostanie ponownie wykonane, a funkcja setState zadziała.React setState nie działa przy pierwszej próbie, ale działa na drugim?

var Flavor = React.createClass({ 
    getInitialState: function() { 
    return { foods: {}, selectedFoods: [], affinities: [] }; 
    }, 
     componentDidMount: function() { 
      $.ajax({ 
       url: this.props.url, 
       dataType: 'json', 
       cache: false, 
       success: function(data) { 
       this.setState({foods: data}); 
       }.bind(this), 
       error: function(xhr, status, err) { 
       console.error(this.props.url, status, err.toString()); 
       }.bind(this) 
      }); 
      }, 
    componentDidUpdate: function() { 
    $('#select-food').selectize({ 
     onChange: this.handleSelection 
     } 
    ); 
    }, 
    handleSelection: function (e) { 
    if (e.target) { 
     var selectedFood = e.target.id; 
    } else { 
     var selectedFood = e; 
    } 
    console.log(selectedFood); 

    if (this.state.foods[selectedFood]) { 
     var selections = this.state.selectedFoods; 
     var newSelections = selections.concat(selectedFood); 
     console.log("newSelections: "+newSelections) 
     var state = Object.assign(this.state, {selectedFoods: newSelections}); 
     this.setState(state); 
     console.log("state: "+this.state.selectedFoods) 
     this.handleAffinities(); 
    } else { 
     console.log("** "+selectedFood+" **"); 
    } 

    }, 
    handleAffinities: function() { 

    console.log("selectedFoods: "+this.state.selectedFoods.length) 
    if (this.state.selectedFoods.length > 0) { 
     var allAffinities = this.state.selectedFoods.map((food) => { 
     return this.state.foods[food]; 
     }); 
     console.log(allAffinities.length); 
     console.log(allAffinities); 

     var commonAffinities = allAffinities[0]; 

     allAffinities.forEach((affinities) => { 
     commonAffinities = commonAffinities.filter((n) => { 
      return affinities.indexOf(n) != -1; 
     }); 
     }) 

     this.setState({affinities: commonAffinities}); 
    } else { 
     this.setState({ affinities: [] }); 
    } 

    }, 
    handleRemove: function(food) { 
    var selectedFoods = this.state.selectedFoods; 
    var index = selectedFoods.indexOf(food); 
    var updatedSelection = selectedFoods.splice(index, 1); 
    this.setState({selectedFoods: selectedFoods}); 
    this.handleAffinities(); 
    }, 

Dlaczego wszystko wykonuje się poprawnie za pierwszym razem, z wyjątkiem mojej funkcji setState? I dlaczego działa na drugim kliknięciu?

+0

Jakieś szanse, że twoje 'if (this.state.foods [selectedFood])' nie jest ważne z jakiegoś powodu? może 'this.state.foods' jest wciąż pusty za pierwszym razem lub coś w tym stylu? –

+0

Co zawiera funkcja 'getInitialState'? Czy możesz opublikować cały komponent, być może w JSFiddle? –

+0

dziękuję, dodałem wszystko do metody renderowania – exchez

Odpowiedz

18

Stan zmienia się dokładnie tak, jak powinien. Problem polega na tym, że twoje instrukcje console.log bezpośrednio po Twoim połączeniu z setState wystrzeliwują przed ustawieniem nowego stanu.

Z docs:

setState() nie od razu mutować this.state ale tworzy oczekującą przejście stanu. Uzyskanie dostępu do this.state po wywołaniu tej metody może potencjalnie zwrócić istniejącą wartość.

Jeśli chcesz wystrzelić console.log oświadczenie po zakończeniu przejściowy stan, przekazać funkcję jako callback do setState().

this.setState({selectedFoods: newSelections},() => { 
    console.log(this.state.selectedFoods); 
}); 
+2

to jest naprawdę dobrze wiedzieć. stan mojego składnika nie jest aktualizowany również przez dowody, że DOM nie zmienia się zgodnie z zamierzeniem. – exchez

+0

Po prostu zwróciłem uwagę na to, że zmagałem się z funkcją przełączania, w której potrzebowałem czegoś takiego: "Natychmiast po tym .setState potrzebowałem funkcji do uruchomienia. Rozwiązałem ją, przekazując tę ​​funkcję w ramach wywołania zwrotnego setState jako @Michael powiedział i zadziałało fantastycznie –

+0

Dziękuję za to! Miałem ból głowy czasu próbuje to zrozumieć Teraz wszystkie moje setState używa wywołania zwrotnego i nie mam problemów. – Timmo