反应挂钩:将状态 setter 作为参数传递给异步函数
react hooks: Pass a state setter as an argument to an async function
Tl;Dr - 我可以将 useState
setter 作为参数传递给 async
函数吗?异步函数将发出请求,然后在成功时使用状态 setter.
存储响应
示范[=15=]
const getResource = async (setResponse) => {
const apiResponse = await axios.get(<Some_URL>)
if (apiResponse) {
setResponse(apiResponse)
}
}
SomePage = () => {
const [response, setResponse] = useState(null)
useEffect(() => {
getResource(setResponse)
}, [])
return (
{ response && <SomeComponent data={response}/> }
)}
在 react hooks 文档中,我注意到类似的东西,它们将 setter 传递给看似异步的函数 ChatApi.SubsrcibeToSomething(..., setter)
,所以这就是我问的原因。我想了解这是否是一种可接受的做法,或者我是否可能在这里遗漏了一些行为可能变得不稳定的东西。我是 React 新手,请多多包涵 - 感谢任何 tips/best 处理 request/response 的做法以及如何存储对状态的响应(React 挂钩)
您有两种选择可以将响应保存在带挂钩的状态中。
- 最佳做法是在 useEffect 中使用挂钩。 (这是最好的选择,因为如果 parent 决定如何处理响应,调用的函数将更具可重用性和“原子性”)
- 第二种选择是在进行调用的函数中传递挂钩(根据问题,这就是您想要的)。
我给你一个class,你可以复制和粘贴来测试它实现的两个选项。
import axios from 'axios';
import { useEffect, useState } from 'react';
const Question1 = () => {
const [response, setResponse] = useState(null);
const getResource = async () => {
return await axios.get("https://api.publicapis.org/entries")
.then(response => response.data)
.catch(() => ({ count: 0, entries: null}));
}
const getResource2 = async (setter) => {
return await axios.get("https://api.publicapis.org/entries")
.then(response => {
setter(response.data);
})
.catch(() => {
setter({ count: 0, entries: null})
});
}
useEffect(() => {
/*
// Option 1
getResource().then(data => {
setResponse(data);
});
*/
// Option 2
getResource2(setResponse);
}, [])
return (<div>
{ response && (<div>{response.count}</div>)}
</div>)
}
export default Question1;
希望对你有所帮助。
可以吗?是的,你绝对可以做到。这是有效的语法。你应该吗?现在这可能有点主观。
您的实施:
const getResource = async (setResponse) => {
const apiResponse = await axios.get(<Some_URL>)
if (apiResponse) {
setResponse(apiResponse);
}
};
const SomePage = () => {
const [response, setResponse] = useState(null);
useEffect(() => {
getResource(setResponse);
}, []);
return response ? <SomeComponent data={response}/> : null'
};
这类似于传递成功回调。如果您使用过基于 Promise 的 APIs 调用函数并传递成功和失败回调,这应该很熟悉。
示例:asynchronousCall(onSuccess, onFailure)
甚至只是 new Promise((resolve, reject) => { .... });
这里的好处是 API 对于提供回调的组件来说很简单。
const [response, setResponse] = useState(null);
useEffect(() => {
getResource(setResponse); // <-- just pass the setter
}, []);
缺点是拥有 response
状态的组件有效地卸载了外部代码维护任何状态不变量的责任,即“第 3 方”代码需要知道什么和如何调用回调以及传递什么。在很多情况下,您都编写了这两个部分并且可以使其工作。但有时情况并非如此。
最好传递一个只是消耗一个值并且父处理更新其内部状态的回调。
const getResource = async (setResponse) => {
const apiResponse = await axios.get(<Some_URL>)
if (apiResponse) {
setResponse(apiResponse);
}
};
const SomePage = () => {
const [response, setResponse] = useState(null);
const responseHandler = response => {
// business logic
setResponse(computedResponseValue);
};
useEffect(() => {
getResource(responseHandler);
}, []);
return response ? <SomeComponent data={response}/> : null'
};
此处的父组件传递一个处理程序,该处理程序采用响应值并管理它希望如何更新状态。
最好简单地 return 将一个值返回给调用者并让他们处理它。
const getResource = async () => {
const apiResponse = await axios.get(<Some_URL>)
return apiResponse;
};
const SomePage = () => {
const [response, setResponse] = useState(null);
useEffect(() => {
getResource()
.then(response => {
// business logic
setResponse(computedResponseValue);
});
}, []);
return response ? <SomeComponent data={response}/> : null'
};
现在的好处是 getResource
很简单,只需要 return 一个已解析的值,并且组件保持对响应处理的控制。
Tl;Dr - 我可以将 useState
setter 作为参数传递给 async
函数吗?异步函数将发出请求,然后在成功时使用状态 setter.
示范[=15=]
const getResource = async (setResponse) => {
const apiResponse = await axios.get(<Some_URL>)
if (apiResponse) {
setResponse(apiResponse)
}
}
SomePage = () => {
const [response, setResponse] = useState(null)
useEffect(() => {
getResource(setResponse)
}, [])
return (
{ response && <SomeComponent data={response}/> }
)}
在 react hooks 文档中,我注意到类似的东西,它们将 setter 传递给看似异步的函数 ChatApi.SubsrcibeToSomething(..., setter)
,所以这就是我问的原因。我想了解这是否是一种可接受的做法,或者我是否可能在这里遗漏了一些行为可能变得不稳定的东西。我是 React 新手,请多多包涵 - 感谢任何 tips/best 处理 request/response 的做法以及如何存储对状态的响应(React 挂钩)
您有两种选择可以将响应保存在带挂钩的状态中。
- 最佳做法是在 useEffect 中使用挂钩。 (这是最好的选择,因为如果 parent 决定如何处理响应,调用的函数将更具可重用性和“原子性”)
- 第二种选择是在进行调用的函数中传递挂钩(根据问题,这就是您想要的)。
我给你一个class,你可以复制和粘贴来测试它实现的两个选项。
import axios from 'axios';
import { useEffect, useState } from 'react';
const Question1 = () => {
const [response, setResponse] = useState(null);
const getResource = async () => {
return await axios.get("https://api.publicapis.org/entries")
.then(response => response.data)
.catch(() => ({ count: 0, entries: null}));
}
const getResource2 = async (setter) => {
return await axios.get("https://api.publicapis.org/entries")
.then(response => {
setter(response.data);
})
.catch(() => {
setter({ count: 0, entries: null})
});
}
useEffect(() => {
/*
// Option 1
getResource().then(data => {
setResponse(data);
});
*/
// Option 2
getResource2(setResponse);
}, [])
return (<div>
{ response && (<div>{response.count}</div>)}
</div>)
}
export default Question1;
希望对你有所帮助。
可以吗?是的,你绝对可以做到。这是有效的语法。你应该吗?现在这可能有点主观。
您的实施:
const getResource = async (setResponse) => {
const apiResponse = await axios.get(<Some_URL>)
if (apiResponse) {
setResponse(apiResponse);
}
};
const SomePage = () => {
const [response, setResponse] = useState(null);
useEffect(() => {
getResource(setResponse);
}, []);
return response ? <SomeComponent data={response}/> : null'
};
这类似于传递成功回调。如果您使用过基于 Promise 的 APIs 调用函数并传递成功和失败回调,这应该很熟悉。
示例:asynchronousCall(onSuccess, onFailure)
甚至只是 new Promise((resolve, reject) => { .... });
这里的好处是 API 对于提供回调的组件来说很简单。
const [response, setResponse] = useState(null);
useEffect(() => {
getResource(setResponse); // <-- just pass the setter
}, []);
缺点是拥有 response
状态的组件有效地卸载了外部代码维护任何状态不变量的责任,即“第 3 方”代码需要知道什么和如何调用回调以及传递什么。在很多情况下,您都编写了这两个部分并且可以使其工作。但有时情况并非如此。
最好传递一个只是消耗一个值并且父处理更新其内部状态的回调。
const getResource = async (setResponse) => {
const apiResponse = await axios.get(<Some_URL>)
if (apiResponse) {
setResponse(apiResponse);
}
};
const SomePage = () => {
const [response, setResponse] = useState(null);
const responseHandler = response => {
// business logic
setResponse(computedResponseValue);
};
useEffect(() => {
getResource(responseHandler);
}, []);
return response ? <SomeComponent data={response}/> : null'
};
此处的父组件传递一个处理程序,该处理程序采用响应值并管理它希望如何更新状态。
最好简单地 return 将一个值返回给调用者并让他们处理它。
const getResource = async () => {
const apiResponse = await axios.get(<Some_URL>)
return apiResponse;
};
const SomePage = () => {
const [response, setResponse] = useState(null);
useEffect(() => {
getResource()
.then(response => {
// business logic
setResponse(computedResponseValue);
});
}, []);
return response ? <SomeComponent data={response}/> : null'
};
现在的好处是 getResource
很简单,只需要 return 一个已解析的值,并且组件保持对响应处理的控制。