Reactjs 使用React钩子强制触发异步请求

Reactjs 使用React钩子强制触发异步请求,reactjs,react-hooks,Reactjs,React Hooks,我无法决定如何强制触发API调用,例如,在单击按钮时。 我不确定使用钩子的正确方法是什么,因为似乎不止一种方法,但我不知道哪种方法是“最好的”方法以及最终的含义 我发现以下示例非常简单,可以做我想做的事情: 将useEffect()与触发器值一起使用 函数SomeFunctionComponent(){ const[fakeData,setFakeData]=useState(0); const[trigger,setTrigger]=useState(false); 异步函数fetchData

我无法决定如何强制触发API调用,例如,在单击按钮时。
我不确定使用钩子的正确方法是什么,因为似乎不止一种方法,但我不知道哪种方法是“最好的”方法以及最终的含义

我发现以下示例非常简单,可以做我想做的事情:

将useEffect()与触发器值一起使用
函数SomeFunctionComponent(){
const[fakeData,setFakeData]=useState(0);
const[trigger,setTrigger]=useState(false);
异步函数fetchData(){
如果(!触发器)返回;
const newData=等待someAPI.fetch();
设置触发器(假);
setFakeData(新数据);
}
useffect(()=>{
fetchData();
},[触发];
返回(
{fakeData}

setTrigger(!trigger)}>刷新 ); }

只需调用API,然后调用setState()
函数SomeFunctionComponent(){
const[fakeData,setFakeData]=useState(0);
异步函数fetchData(){
const newData=等待someAPI.fetch();
setFakeData(新数据);
}
返回(
{fakeData}

刷新 ); }

还有其他一些方法可以利用useCallback(),但据我所知,它们对于在向下传递回调时避免重新呈现子组件非常有用,与第二个示例相当

我认为useEffect方法只有在必须以编程方式在组件挂载上运行时才有用,但本质上是一个伪值来触发副作用看起来很冗长。
仅仅调用函数看起来非常实用和简单,但我不确定是否允许函数组件在渲染期间执行副作用


在React中使用hooks进行命令式调用,哪种方法最惯用、最正确?

当我试图找出写东西的最佳方法时,我要做的第一件事就是看看我想如何使用它。在您的情况下,此代码:

    <React.Fragment>
      <p>{fakeData}</p>
      <button onClick={fetchData}>Refresh</button>
    </React.Fragment>

被接受的答案实际上打破了这一界限。由于单击是异步的,这意味着在fetch调用期间可能会发生其他渲染,这将产生副作用,可能会产生可怕的效果

我们可以通过在调用
setState()
函数之前检查组件是否已装入来修复它。下面是我的解决方案,它相当容易使用

挂钩功能

函数useApi(actionAsync,initialResult){ 常量[loading,setLoading]=React.useState(false); const[result,setResult]=React.useState(initialResult); const[fetchFlag,setFetchFlag]=React.useState(0); React.useffect(()=>{ 如果(fetchFlag==0){ //仅在调用triggerFetch后运行 返回; } 让我们假设这是真的; 设置加载(真); actionAsync()。然后(res=>{ 如果(已安装){ //仅当组件仍然安装时才修改状态 设置加载(假); 设置结果(res); } }) //表示compnoent已“清理”的信号 返回()=>mounted=false; },[fetchFlag]) 函数triggerFetch(){ //设置fetchFlag以间接触发上述useEffect setFetchFlag(Math.random()); } 返回[结果、triggerFetch、加载]; } 在React hook中的用法

函数MyComponent(){
异步函数fetchUsers(){
const data=wait fetch(“myapi”)。然后((r)=>r.json();
返回数据;
}
const[fetchResult,fetchTrigger,fetchLoading]=useApi(fetchUsers,null);
返回(
刷新用户
{fetchLoading?“正在加载”:“完成”}

{JSON.stringify(fetchResult)} ); }
如果您只想在单击按钮时运行效果,那么仅仅为了运行效果而引入一段状态会让您觉得浪费。如果您想在道具发生变化时再次提取数据,那么使用效果是有意义的,但在这种情况下,您也可以在事件处理程序中提取数据。如果您想在装载时加载效果(第二个选项),只需使用
useffect
调用
useffect
中的
fetchData
函数,以确保只运行一次。我想,像往常一样,简单和直接的事情是最好的。我认为功能组件中的所有副作用都必须在useEffect中执行?为什么这里不是这样?谢谢,这不是副作用。这是一个用户生成的动作onClick@AlonBarDavid用户生成的操作实际上是一种副作用,对吗?如果
SomeFunctionComponent
在调用
setData()
之前被销毁,那么它将抛出一个错误。对于提供的每个实现,如果我们在销毁组件之后使用setData,则会发生错误。这与副作用无关,您必须在某个时候影响组件状态才能重新提交新数据。为了防止这种情况,正确的方法是在使用useEffect的返回调用销毁组件时取消api请求。虽然在库代码之外,但很少这样做,因为它需要大量的样板文件,我们通常可以假设它不会发生,或者我们不在乎如果发生了警告。