使用 useState 钩子的反应组件是否会重新呈现每个 setState 调用?
Does a react component using useState hook rerender every `setState` call?
https://codesandbox.io/s/mow5zl5729
import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
function useLoading() {
const [isLoading, setLoading] = React.useState(true);
const [hasError, setError] = React.useState(false);
const loadStuff = aPromise => {
return aPromise
.then(() => {
setLoading(false);
})
.catch(() => {
setLoading(false);
setError(true);
});
};
return { isLoading, hasError, loadStuff };
}
function App() {
const { isLoading, hasError, loadStuff } = useLoading();
useEffect(() => {
loadStuff(axios.get(`https://google.com`));
}, []);
console.log(isLoading, hasError);
return <div />;
}
这是我的意思的一个简化示例。
如果 useLoading
中的 promise 被拒绝,我会期望组件在挂载时呈现,然后在捕获到错误时第二次呈现。因此,我预计总共有 2 个具有以下状态的渲染:
第一次渲染:
- 正在加载:真
- 有错误:错误
第二次渲染:
- 正在加载:假
- 有错误:真
相反,组件似乎在 setLoading(false)
之后重新呈现一次,在 setError(true)
之后再次呈现。所以,我明白了:
第一次渲染:
- 正在加载:真
- 有错误:错误
第二次渲染:(为什么?)
- 正在加载:假
- 有错误:错误
第三次渲染:
- 正在加载:假
- 有错误:真
我怀疑这个问题不知何故是我在 useEffect
中使用了 promise,但我不确定我的心智模型哪里出了问题。
编辑:
当我将 useLoading
更改为仅包含 1 useState
时,问题就消失了。
损坏:
const [isLoading, setLoading] = React.useState(true);
const [hasError, setError] = React.useState(false);
作品:
const [loadingState, setLoadingState] = React.useState({
loading: true,
error: false
});
看起来这与状态更新的批处理有关。据我所知,基于 React 的事件会触发批量更新,但不会触发外部事件。 promise
在这种情况下。
因为状态调用不是批处理的,所以您会看到 2nd render
两者都设置为 false
https://codesandbox.io/s/mow5zl5729
import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
function useLoading() {
const [isLoading, setLoading] = React.useState(true);
const [hasError, setError] = React.useState(false);
const loadStuff = aPromise => {
return aPromise
.then(() => {
setLoading(false);
})
.catch(() => {
setLoading(false);
setError(true);
});
};
return { isLoading, hasError, loadStuff };
}
function App() {
const { isLoading, hasError, loadStuff } = useLoading();
useEffect(() => {
loadStuff(axios.get(`https://google.com`));
}, []);
console.log(isLoading, hasError);
return <div />;
}
这是我的意思的一个简化示例。
如果 useLoading
中的 promise 被拒绝,我会期望组件在挂载时呈现,然后在捕获到错误时第二次呈现。因此,我预计总共有 2 个具有以下状态的渲染:
第一次渲染:
- 正在加载:真
- 有错误:错误
第二次渲染:
- 正在加载:假
- 有错误:真
相反,组件似乎在 setLoading(false)
之后重新呈现一次,在 setError(true)
之后再次呈现。所以,我明白了:
第一次渲染:
- 正在加载:真
- 有错误:错误
第二次渲染:(为什么?)
- 正在加载:假
- 有错误:错误
第三次渲染:
- 正在加载:假
- 有错误:真
我怀疑这个问题不知何故是我在 useEffect
中使用了 promise,但我不确定我的心智模型哪里出了问题。
编辑:
当我将 useLoading
更改为仅包含 1 useState
时,问题就消失了。
损坏:
const [isLoading, setLoading] = React.useState(true);
const [hasError, setError] = React.useState(false);
作品:
const [loadingState, setLoadingState] = React.useState({
loading: true,
error: false
});
看起来这与状态更新的批处理有关。据我所知,基于 React 的事件会触发批量更新,但不会触发外部事件。 promise
在这种情况下。
因为状态调用不是批处理的,所以您会看到 2nd render
两者都设置为 false