Junior
Jak poprawnie zmieniać stan komponentów w React?
sobes.tech AI
Odpowiedź od AI
Zmiana stanu w React zachodzi za pomocą metody setState dla komponentów klasowych lub za pomocą hooka useState dla komponentów funkcyjnych.
Komponenty klasowe:
// Import React
import React, { Component } from 'react';
// Tworzymy komponent klasowy
class MyComponent extends Component {
// Inicjujemy stan
constructor(props) {
super(props);
this.state = {
count: 0
};
}
// Metoda do zmiany stanu
incrementCount = () => {
// Używamy setState
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>Licznik: {this.state.count}</p>
<button onClick={this.incrementCount}>Zwiększ</button>
</div>
);
}
}
// Eksportujemy komponent
export default MyComponent;
setStatejest asynchroniczne.setStatełączy nowy stan z obecnym (shallow merge).setStatemoże przyjąć funkcję zwracającą nowy stan oparty na poprzednim:
// Metoda do zmiany stanu z użyciem funkcji
incrementCountFunction = () => {
this.setState((prevState) => ({
count: prevState.count + 1
}));
};
Komponenty funkcyjne (z użyciem useState):
// Import React i useState
import React, { useState } from 'react';
// Tworzymy komponent funkcyjny
function MyFunctionComponent() {
// Inicjujemy stan za pomocą useState
const [count, setCount] = useState(0); // [obecny stan, funkcja do aktualizacji]
// Funkcja do zmiany stanu
const incrementCount = () => {
// Używamy funkcji do aktualizacji
setCount(count + 1);
};
return (
<div>
<p>Licznik: {count}</p>
<button onClick={incrementCount}>Zwiększ</button>
</div>
);
}
// Eksportujemy komponent
export default MyFunctionComponent;
useStatezwraca tablicę z dwoma elementami: obecnym stanem i funkcją do jego aktualizacji.- Funkcja do aktualizacji stanu, zwracana przez
useState, zastępuje obecny stan, a nie go łączy. - Można przekazać funkcję do funkcji aktualizacji, jeśli nowy stan zależy od poprzedniego:
// Funkcja do zmiany stanu z użyciem funkcji
const incrementCountFunction = () => {
setCount(prevCount => prevCount + 1);
};
Ważne punkty przy zmianie stanu:
- Nie modyfikuj bezpośrednio stanu: Nigdy nie przypisuj nowej wartości do właściwości
statebezpośrednio (np.this.state.count = 5lubcount = 5). React nie wykryje tej zmiany i komponent nie zostanie ponownie wyrenderowany. - Zmiana obiektów i tablic: Przy zmianie obiektów lub tablic w stanie, zawsze twórz nowe kopie. React porównuje odwołania do obiektów/tablic, i jeśli odwołanie się nie zmienia, React zakłada, że dane się nie zmieniły i nie wywołuje ponownego renderowania.
// Zmiana obiektu w komponencie klasowym
this.setState(prevState => ({
user: {
...prevState.user, // Kopiujemy stare właściwości
name: 'Nowa nazwa' // Aktualizujemy potrzebną właściwość
}
}));
// Zmiana tablicy w komponencie funkcyjnym
setItems(prevItems => [...prevItems, 'Nowy element']); // Dodajemy nowy element
- Asynchroniczność
setState: Jeśli chcesz wykonać akcję po tym, jak stan zostanie zaktualizowany i komponent ponownie się wyrenderuje, użyj drugiego argumentusetState(funkcji zwrotnej) lub hookauseEffectw komponentach funkcyjnych.
// Callback w setState
this.setState({ count: this.state.count + 1 }, () => {
console.log('Stan zaktualizowany!');
});
// useEffect do reagowania na zmianę stanu
useEffect(() => {
console.log('Stan count się zmienił:', count);
}, [count]); // Zależność: hook zostanie wywołany przy zmianie count
Porównanie metod:
| Cecha | Komponent klasowy (setState) |
Komponent funkcyjny (useState) |
|---|---|---|
| Składnia | Metoda this.setState(newState[, callback]) |
Hook const [state, setState] = useState(initialState) |
| Łączenie/Zamiana | Łączy nowy stan z obecnym (shallow merge) | Zastępuje obecny stan nowym |
| Asynchroniczność | Asynchroniczne | Funkcja aktualizacji jest asynchroniczna przy wywołaniu z obsługi zdarzeń, ale synchroniczna podczas fazy renderowania React |
| Zależność od poprzedniego stanu | Przekazanie funkcji do setState: this.setState(prevState => ({...})) |
Przekazanie funkcji do funkcji aktualizacji: setState(prev => ({...})) |