Reactjs 为什么自定义钩子会返回两次结果
下面的文章是关于创建一个用于获取数据的自定义钩子的,这很简单 但有一部分我不知道它是如何工作的 为什么这个钩子会返回两次结果?(isLoading=true isLoading=false)Reactjs 为什么自定义钩子会返回两次结果,reactjs,react-hooks,Reactjs,React Hooks,下面的文章是关于创建一个用于获取数据的自定义钩子的,这很简单 但有一部分我不知道它是如何工作的 为什么这个钩子会返回两次结果?(isLoading=true isLoading=false) 函数useAPI(方法,…参数){ //----国家 const[data,setData]=useState(null); const[isLoading,setIsLoading]=useState(false); const[error,setError]=useState(null); //---
函数useAPI(方法,…参数){
//----国家
const[data,setData]=useState(null);
const[isLoading,setIsLoading]=useState(false);
const[error,setError]=useState(null);
//----API
const fetchData=async()=>{
onError(空);
试一试{
设置加载(真);
setData(等待APIService[method](…params));
}捕获(e){
设置错误(e);
}最后{
设置加载(假);
}
};
useffect(()=>{fetchData()},[]);
返回[data,isLoading,error,fetchData];
}
功能主屏幕(){
const[users,isLoading,error,retry]=useAPI('loadUsers');
//---显示错误
如果(错误){
返回
}
//---模板
返回(
{
(users&&users.length>0)&&
}
)
您的最后
块在尝试
块后启动
请注意,无论是否引发异常,finally块都会执行
在事件处理程序和生命周期方法中反应批处理状态更新
fetchData
不是其中任何一个,因此不会发生批处理
现在,当调用fetchData()
时:
成功时,会出现3
异步事件,我们只对#1
和#3
- 将加载状态从默认值设置为
true
- 从
async#1
将加载状态设置为setState
false
fetchData
在每次渲染时都会被重新分配,您将收到缺少依赖项的警告
你预计会发生什么?所以所有状态更新都会被返回,除非它是事件处理程序或生命周期方法。好吧,我猜状态更新会被返回。是否有文档链接。我知道每个人都希望它像这样工作,但作为一个新手,我感到惊讶。这是一个内部实现,所以你应该如果我不考虑它,你可以阅读更多。好的thx,那么如果我将逻辑移出fetchdata,更新将被批处理,整个事情将被破坏,我会尝试。这不是我提到的旁注的解决方案,如何修复它超出了当前问题的范围。是的,我不是指旁注,而是指我的理解批处理与非批处理行为的比较。
function useAPI(method, ...params) {
// ---- State
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
// ---- API
const fetchData = async () => {
onError(null);
try {
setIsLoading(true);
setData(await APIService[method](...params));
} catch (e) {
setError(e);
} finally {
setIsLoading(false);
}
};
useEffect(() => { fetchData() }, []);
return [ data, isLoading, error, fetchData ];
}
function HomeScreen() {
const [ users, isLoading, error, retry ] = useAPI('loadUsers');
// --- Display error
if (error) {
return <ErrorPopup msg={error.message} retryCb={retry}></ErrorPopup>
}
// --- Template
return (
<View>
<LoadingSpinner loading={isLoading}></LoadingSpinner>
{
(users && users.length > 0) &&
<UserList users={users}></UserList>
}
</View>
)
const fetchData = async () => {
onError(null);
try {
// #1 async setState
setIsLoading(true);
const data = await APIService[method](...params);
// #2 async setState
setData(data);
} catch (e) {
setError(e);
} finally {
// #3 async setState
setIsLoading(false);
}
};