[英]React Hook : Correct way of using custom hook to handle onClick Event?
正如标题所说,使用自定义钩子处理 onClick 事件的正确方法是什么?
当用户单击搜索按钮时,此 代码框应用程序将在屏幕上显示新报价。
function App() {
const [{ data, isLoading, isError }, doFetch] = useDataApi(
"https://api.quotable.io/random"
);
return (
<Fragment>
<button disabled={isLoading} onClick={doFetch}>
Search
</button>
{isError && <div>Something went wrong ...</div>}
{isLoading ? <div>Loading ...</div> : <div>{data.content}</div>}
</Fragment>
);
}
我创建了一个名为useDataApi()
的自定义钩子,它将从 API 获取新报价。 为了在用户单击按钮时更新报价,在useDataApi()
内,我创建了一个handleClick()
,它将更改单击值的值以触发重新渲染。 这个handleClick()
function 将返回给App()
const useDataApi = initialUrl => {
const [data, setData] = useState("");
const [click, setClick] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const handleClick = () => {
setClick(!click);
};
useEffect(() => {
const fetchData = async () => {
setIsError(false);
setIsLoading(true);
try {
const result = await axios(initialUrl);
setData(result.data);
} catch (error) {
setIsError(true);
}
setIsLoading(false);
};
fetchData();
}, [initialUrl, click]);
return [{ data, isLoading, isError }, handleClick];
};
这是可行的,但是,我认为这不是正确的解决方案。
我还尝试将fetchData()
移出useEffect
并返回fetchData()
,它也可以工作。 但是根据React Doc ,它说建议在useEffect
中移动函数。
const useDataApi = initialUrl => {
const [data, setData] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const fetchData = async () => {
setIsError(false);
setIsLoading(true);
try {
const result = await axios(initialUrl);
setData(result.data);
} catch (error) {
setIsError(true);
}
setIsLoading(false);
};
useEffect(() => {
fetchData();
}, []);
return [{ data, isLoading, isError }, fetchData];
};
此外,对于创建这些类型的应用程序,我使用的方式是好的还是有其他正确的解决方案,例如不使用任何useEffects
或不创建任何自定义 Hook? 谢谢
不确定这是否正确,但这是我的解决方案。
const useDataApi = initialUrl => {
const [data, setData] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const doFetch = async () => {
setIsError(false);
setIsLoading(true);
try {
const result = await axios(initialUrl);
setData(result.data);
} catch (error) {
setIsError(true);
}
setIsLoading(false);
};
return [{ data, isLoading, isError }, doFetch];
};
顺便说一句,不要直接变异 state 。
const handleClick = () => {
setClick(!click); // don't do this
setClick(prev => !prev); // use this
};
你的实现很好。 我们也在使用类似的东西。 希望你觉得它有用。
function useApi(promiseFunction, deps, shouldRun=true){ // promisFunction returns promise const [loading, setLoading] = useState(false) const [data, setData] = useState(false) const [error, setError] = useState(false) const dependencies: any[] = useMemo(()=>{ return [...dependencyArray, shouldRun] },[...dependencyArray, shouldRun]) const reload = () => { async function call() { try { setError(null) setLoading(true) const res = await promiseFunction(); } catch (error) { setError(error) } finally { setLoading(false) } } call(); } useEffect(() => { if(,shouldRun) return setResult(null) //no stale data reload() }, dependencies) return {loading, error, data, reload: setState: setData} }
下面的代码将提供一些关于如何使用它的想法。
function getUsersList(){ return fetch('/users') } function getUserDetail(id){ return fetch(`/user/${id}`) } const {loading, error, data } = useApi(getUsersList, [], true) const {loading: userLoading, error: userError, data: userData} = useApi(()=>getUserDetail(id), [id], true)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.