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
内部使用诺言,但是我不确定我的思维模式出了什么问题。
编辑:
当我将useLoading
更改为仅包含1个useState
时,问题就消失了。
残破:
const [isLoading, setLoading] = React.useState(true);
const [hasError, setError] = React.useState(false);
有效:
const [loadingState, setLoadingState] = React.useState({
loading: true,
error: false
});
答案 0 :(得分:2)
看起来这与状态更新的批处理有关。据我所知,基于React的事件将触发批处理更新,但不会触发在其外部触发的更新。 promise
。
由于状态调用未批处理,因此您看到2nd render
都设置为false