Chciałbym zapytać, dlaczego mój stan się nie zmienia, kiedy robię wydarzenie onclick. Szukałem jakiś czas temu, że muszę powiązać funkcję onclick w konstruktorze, ale nadal stan nie jest aktualizowany. Oto mój kod:
import React from 'react';
import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import BoardAddModal from 'components/board/BoardAddModal.jsx';
import style from 'styles/boarditem.css';
class BoardAdd extends React.Component {
constructor(props){
super(props);
this.state = {
boardAddModalShow: false
}
this.openAddBoardModal = this.openAddBoardModal.bind(this);
}
openAddBoardModal(){
this.setState({ boardAddModalShow: true });
// After setting a new state it still return a false value
console.log(this.state.boardAddModalShow);
}
render() {
return (
<Col lg={3}>
<a href="javascript:;" className={style.boardItemAdd} onClick={this.openAddBoardModal}>
<div className={[style.boardItemContainer,style.boardItemGray].join(' ')}>
Create New Board
</div>
</a>
</Col>
)
}
}
export default BoardAdd
javascript
reactjs
ecmascript-6
Sydney Loteria
źródło
źródło
setState
nie zwraca obietnicy. Jeśli zadziałało, zadziałało tylko dlatego, żeawait
wprowadza do funkcji jeden asynchroniczny „tik” i zdarzyło się, że aktualizacja stanu została przetworzona podczas tego tiku. To nie jest gwarantowane. Jak mówi ta odpowiedź , musisz użyć wywołania zwrotnego zakończenia (jeśli naprawdę musisz coś zrobić po aktualizacji stanu, co jest niezwykłe; zwykle chcesz po prostu ponownie renderować, co dzieje się automatycznie).Odpowiedzi:
To oddzwonienie jest naprawdę nieuporządkowane. Zamiast tego użyj async await:
async openAddBoardModal(){ await this.setState({ boardAddModalShow: true }); console.log(this.state.boardAddModalShow); }
źródło
setState
nie zwraca obietnicy.setState
nie zwraca obietnicy, więc NIE należy jej czekać. To powiedziawszy, myślę, że rozumiem, dlaczego to działa dla niektórych osób, ponieważ await umieszcza wewnętrzne działanie setState na stosie wywołań przed resztą funkcji, więc jest przetwarzane jako pierwsze, a zatem wydaje się, że stan został zestaw. Jeśli setState ma lub zaimplementuje jakiekolwiek nowe wywołania asynchroniczne, ta odpowiedź nie powiedzie się. Aby poprawnie zaimplementować tę funkcję, możesz użyć tego:await new Promise(resolve => this.setState({ boardAddModalShow: true }, () => resolve()))
async this.setState({})
rozwiązał mój problem? Mieliśmy działający kod, trochę więcej prac programistycznych, ale nic nie zmieniło tej części aplikacji. Tylko jeden z dwóch obiektów w setState był aktualizowany, co sprawiło, że async przywrócił funkcjonalność, a teraz oba obiekty są poprawnie aktualizowane. Nie mam pojęcia, co do cholery było nie tak.Twój stan potrzebuje trochę czasu, aby się zmutować, a ponieważ jest
console.log(this.state.boardAddModalShow)
wykonywany przed mutacją stanu, na wyjściu otrzymujesz poprzednią wartość. Musisz więc napisać konsolę w wywołaniu zwrotnym dosetState
funkcjiopenAddBoardModal() { this.setState({ boardAddModalShow: true }, function () { console.log(this.state.boardAddModalShow); }); }
setState
jest asynchroniczna. Oznacza to, że nie możesz wywołać tego w jednej linii i założyć, że stan zmienił się w następnej.Według dokumentów React
Dlaczego mieliby tworzyć
setState
asynchroniczneźródło
console.log
ustawiam rekwizyt, otrzymuję tę samą wartość, co stan oryginalny.Na szczęście
setState()
odbiera oddzwonienie. I tutaj otrzymujemy zaktualizowany stan.Rozważmy ten przykład.
this.setState({ name: "myname" }, () => { //callback console.log(this.state.name) // myname });
Dlatego po uruchomieniu wywołania zwrotnego this.state jest zaktualizowanym stanem.
Możesz uzyskać
mutated/updated
dane w oddzwonieniu.źródło
initMap()
, na przykładPonieważ setSatate jest funkcją asynchroniczną, musisz konsolidować stan jako wywołanie zwrotne w ten sposób.
openAddBoardModal(){ this.setState({ boardAddModalShow: true }, () => { console.log(this.state.boardAddModalShow) }); }
źródło
setState()
nie zawsze od razu aktualizuje komponent. Może zbiorczo lub odroczyć aktualizację na później. To sprawia, że czytanie this.state zaraz po wywołaniusetState()
potencjalnej pułapki. Zamiast tego użyjcomponentDidUpdate
lubsetState
callback (setState(updater, callback)
), z których każda z nich zostanie uruchomiona po zastosowaniu aktualizacji. Jeśli chcesz ustawić stan na podstawie poprzedniego stanu, przeczytaj o argumencie aktualizującym poniżej.setState()
zawsze doprowadzi do ponownego renderowania, chyba żeshouldComponentUpdate()
zwróci false. Jeśli używane są zmienne obiekty i nie można zaimplementować warunkowej logiki renderowaniashouldComponentUpdate()
, wywołaniesetState()
tylko wtedy, gdy nowy stan różni się od poprzedniego, pozwoli uniknąć niepotrzebnego ponownego renderowania.Pierwszy argument to funkcja aktualizująca z podpisem:
state
jest odniesieniem do stanu komponentu w momencie zastosowania zmiany. Nie należy go bezpośrednio mutować. Zamiast tego zmiany powinny być reprezentowane przez budowanie nowego obiektu na podstawie danych wejściowych ze stanu i właściwości. Na przykład załóżmy, że chcemy zwiększyć wartość stanu przez props.step:this.setState((state, props) => { return {counter: state.counter + props.step}; });
źródło
Jeśli chcesz śledzić, czy stan się aktualizuje, czy nie, innym sposobem zrobienia tego samego jest
_stateUpdated(){ console.log(this.state. boardAddModalShow); } openAddBoardModal(){ this.setState( {boardAddModalShow: true}, this._stateUpdated.bind(this) ); }
W ten sposób możesz wywołać metodę „_stateUpdated” za każdym razem, gdy próbujesz zaktualizować stan do debugowania.
źródło
setState()
jest asynchroniczna. Najlepszym sposobem sprawdzenia, czy stan jest aktualizowany, byłobycomponentDidUpdate()
umieszczenieconsole.log(this.state.boardAddModalShow)
pothis.setState({ boardAddModalShow: true })
.według React Docs
źródło
Według React Docs
Przykład:
import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; class App extends React.Component { constructor() { super(); this.state = { counter: 1 }; } componentDidUpdate() { console.log("componentDidUpdate fired"); console.log("STATE", this.state); } updateState = () => { this.setState( (state, props) => { return { counter: state.counter + 1 }; }); }; render() { return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h2>Start editing to see some magic happen!</h2> <button onClick={this.updateState}>Update State</button> </div> ); } } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
źródło
Dla każdego, kto próbuje to zrobić z haczykami, potrzebujesz
useEffect
.function App() { const [x, setX] = useState(5) const [y, setY] = useState(15) console.log("Element is rendered:", x, y) // setting y does not trigger the effect // the second argument is an array of dependencies useEffect(() => console.log("re-render because x changed:", x), [x]) function handleXClick() { console.log("x before setting:", x) setX(10) console.log("x in *line* after setting:", x) } return <> <div> x is {x}. </div> <button onClick={handleXClick}> set x to 10</button> <div> y is {y}. </div> <button onClick={() => setY(20)}> set y to 20</button> </> }
Wynik:
Element is rendered: 5 15 re-render because x changed: 5 (press x button) x before setting: 5 x in *line* after setting: 5 Element is rendered: 10 15 re-render because x changed: 10 (press y button) Element is rendered: 10 20
źródło
kiedy uruchamiałem kod i sprawdzałem moje dane wyjściowe w konsoli, pokazało, że jest niezdefiniowany. Po tym, jak poszukam i znajdę coś, co dla mnie zadziałało.
Dodałem tę metodę w moim kodzie po konstruktorze (). sprawdź cykl życia React Native Workflow.
https://images.app.goo.gl/BVRAi4ea2P4LchqJ8
źródło
this.setState({ isMonthFee: !this.state.isMonthFee, }, () => { console.log(this.state.isMonthFee); })
źródło
Tak, ponieważ setState jest funkcją asynchroniczną. Najlepszym sposobem na ustawienie stanu zaraz po zapisaniu stanu set jest użycie Object. assign w następujący sposób: Na przykład chcesz ustawić właściwość isValid na true, zrób to w ten sposób
Możesz uzyskać dostęp do zaktualizowanego stanu zaraz po napisaniu tej linii.
źródło