#javascript #reactjs #react-hooks #react-state #react-lifecycle
#javascript #reactjs #реагирующие перехваты #реагировать-состояние #реагировать-жизненный цикл
Вопрос:
Я только начал реагировать…
Этот код просто отображается через 3 секунды с использованием логического значения.
Но приведенный ниже код продолжает отображаться.. рендеринг.. рендеринг… почти каждые три секунды.
import React, { useState } from "react";
const App = () => {
const [isLoading, setIsLoading] = useState(true);
setTimeout(() => {
setIsLoading(!isLoading);
}, 3000);
return <h1>{isLoading ? "Loading" : "we are ready"}</h1>;
};
export default App;
Но этот код работает хорошо. В чем причина?
import React, { Component } from "react";
class App extends React.Component {
state = {
isLoading: true,
};
componentDidMount() {
setTimeout(() => {
this.setState({
isLoading: false,
});
}, 3000);
}
render() {
return <div>{this.state.isLoading ? "Loading..." : "we are ready"}</div>;
}
}
export default App;
Ответ №1:
Функциональный компонент вызывается при каждом рендеринге. Это означает, что тайм-аут также создается при каждом повторном рендеринге после изменения состояния, когда он реализован, как в вашем первом примере. Чтобы использовать жизненный цикл компонента, вы должны использовать useEffect
перехват: https://reactjs.org/docs/hooks-reference.html#useeffect
import React, { useEffect, useState } from "react";
const App = () => {
const [isLoading, setIsLoading] = useState(true);
// Set a timeout ONCE when the component is rendered for the first time
// The second argument [] signifies that nothing will trigger the effect during re-renders
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 3000);
}, [])
return <h1>{isLoading ? "Loading" : "we are ready"}</h1>;
};
export default App;
Ответ №2:
Поскольку вы инициализируете загрузку с истинным значением в состоянии. и всякий раз, когда состояние изменяется, функциональные компоненты перезаписываются, и это не происходит в компоненте на основе класса, поскольку вы использовали метод жизненного цикла компонента. Вы должны использовать «useEffect» в функциональном компоненте.
useEffect(() => {
setTimeout(() => {
setIsLoading(!isLoading);
}, 3000);
});
вы можете прочитать об этом здесь https://reactjs.org/docs/hooks-effect.html
Ответ №3:
Ответ от MubtadaNaqvi, к сожалению, приведет к бесконечному циклу. Вы должны правильно применить useEffect:
useEffect(() => {
setTimeout(() => {
setIsLoading(isLoading => !isLoading);
}, 1000);
}, [])
Комментарии:
1. Это тоже не сработает, поскольку установщик не принимает функцию в качестве аргумента.
2. Вы можете указать prevState в setState, и это то, что я сделал.
setIsLoading(false)
был бы еще один вариант.3. Понятно, я думал, что это работает только для компонентов на основе классов.
4. Поступая таким образом, вы избежали бы useEffect linting жалобы на то, что у него отсутствует зависимость, загружается
5. Достаточно справедливо. Хотя в этом случае простая установка его
false
может иметь больше смысла