Czy istnieją sposoby na symulowanie componentDidMount
komponentów funkcjonalnych w React za pomocą hooków?
Odpowiedzi:
Dla stabilnej wersji hooków (wersja React 16.8.0+)
Dla componentDidMount
useEffect(() => {
// Your code here
}, []);
Dla componentDidUpdate
useEffect(() => {
// Your code here
}, [yourDependency]);
Dla componentWillUnmount
useEffect(() => {
// componentWillUnmount
return () => {
// Your code here
}
}, [yourDependency]);
W tej sytuacji musisz przekazać swoją zależność do tej tablicy. Załóżmy, że masz taki stan
const [count, setCount] = useState(0);
Gdy liczba wzrasta, chcesz ponownie wyrenderować komponent funkcji. Wtedy twój useEffect
powinien wyglądać tak
useEffect(() => {
// <div>{count}</div>
}, [count]);
W ten sposób za każdym razem, gdy zaktualizujesz licznik, komponent zostanie ponownie renderowany. Mam nadzieję, że to trochę pomoże.
useState
. Dla każdego, kto to czyta, pamiętaj, że pozostawienie drugiego argumentu undefined
spowoduje wywołanie efektu przy każdym renderowaniu (jeśli się nie mylę).
Chociaż zaakceptowana odpowiedź działa, nie jest zalecana. Kiedy masz więcej niż jeden stan i używasz go z useEffect, ostrzeże Cię o dodaniu go do tablicy zależności lub w ogóle jej nieużywaniu.
Czasami powoduje to problem, który może dać nieprzewidywalne wyniki. Dlatego sugeruję, abyś trochę się postarał, aby przepisać swoją funkcję na klasę. Jest bardzo mało zmian i możesz mieć niektóre komponenty jako klasę, a niektóre jako funkcje. Nie jesteś zobowiązany do używania tylko jednej konwencji.
Weź to na przykład
function App() {
const [appointments, setAppointments] = useState([]);
const [aptId, setAptId] = useState(1);
useEffect(() => {
fetch('./data.json')
.then(response => response.json())
.then(result => {
const apts = result.map(item => {
item.aptId = aptId;
console.log(aptId);
setAptId(aptId + 1);
return item;
})
setAppointments(apts);
});
}, []);
return(...);
}
i
class App extends Component {
constructor() {
super();
this.state = {
appointments: [],
aptId: 1,
}
}
componentDidMount() {
fetch('./data.json')
.then(response => response.json())
.then(result => {
const apts = result.map(item => {
item.aptId = this.state.aptId;
this.setState({aptId: this.state.aptId + 1});
console.log(this.state.aptId);
return item;
});
this.setState({appointments: apts});
});
}
render(...);
}
To tylko przykład . więc nie mówmy o najlepszych praktykach lub potencjalnych problemach z kodem. Oba mają tę samą logikę, ale późniejsza działa tylko zgodnie z oczekiwaniami. Możesz uzyskać funkcjonalność komponentu componentDidMount, gdy useEffect będzie działał przez ten czas, ale wraz z rozwojem Twojej aplikacji mogą wystąpić pewne problemy. Więc zamiast przepisywać na tym etapie, lepiej zrobić to na wczesnym etapie.
Poza tym OOP nie jest takie złe, gdyby wystarczyło programowanie zorientowane na procedury, nigdy nie mielibyśmy programowania obiektowego. Czasami jest to bolesne, ale lepsze (technicznie. Pomijając kwestie osobiste).
Nie ma żadnych componentDidMount
funkcjonalnych komponentów, ale React hooki zapewniają sposób na emulację zachowania za pomocą useEffect
hooka.
Przekaż pustą tablicę jako drugi argument, useEffect()
aby uruchomić wywołanie zwrotne tylko po zamontowaniu.
Przeczytaj dokumentacjęuseEffect
.
function ComponentDidMount() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
console.log('componentDidMount');
}, []);
return (
<div>
<p>componentDidMount: {count} times</p>
<button
onClick={() => {
setCount(count + 1);
}}
>
Click Me
</button>
</div>
);
}
ReactDOM.render(
<div>
<ComponentDidMount />
</div>,
document.querySelector("#app")
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
Nie ma dokładnego odpowiednika dla componentDidMount
haków reakcyjnych.
Z mojego doświadczenia wynika, że reakcja hooków wymaga innego sposobu myślenia podczas jej tworzenia i generalnie nie należy porównywać jej z metodami klasowymi, takimi jak componentDidMount
.
Z powiedział, że istnieją sposoby, które można wykorzystać do produkcji haków podobny efekt do componentDidMount
.
Rozwiązanie 1:
useEffect(() => {
console.log("I have been mounted")
}, [])
Rozwiązanie 2:
const num = 5
useEffect(() => {
console.log("I will only run if my deps change: ", num)
}, [num])
Rozwiązanie 3 (z funkcją):
useEffect(() => {
const someFunc = () => {
console.log("Function being run after/on mount")
}
someFunc()
}, [])
Rozwiązanie 4 (useCallback):
const msg = "some message"
const myFunc = useCallback(() => {
console.log(msg)
}, [msg])
useEffect(() => {
myFunc()
}, [myFunc])
Rozwiązanie 5 (kreatywność):
export default function useDidMountHook(callback) {
const didMount = useRef(null)
useEffect(() => {
if (callback && !didMount.current) {
didMount.current = true
callback()
}
})
}
Warto zauważyć, że rozwiązanie 5 powinno być naprawdę używane tylko wtedy, gdy żadne z innych rozwiązań nie działa w twoim przypadku użycia . Jeśli zdecydujesz, że potrzebujesz rozwiązania 5, polecam użycie tego gotowego haka do montażu .
Źródło (bardziej szczegółowo): Używanie komponentu componentDidMount w zaczepach reagujących
Chcesz użyć useEffect()
, który, w zależności od tego, jak używasz funkcji, może działać podobnie jak componentDidMount ().
Na przykład. można użyć niestandardowej loaded
właściwości stanu, która jest początkowo ustawiona na false, i przełączyć ją na true podczas renderowania i uruchomić efekt tylko wtedy, gdy ta wartość się zmieni.