gol*_*cks 3 reactjs react-hooks
我有很多反应经验,但我是钩子的新手。
我useFetch
在这个useAsync钩子之后修改了以下钩子:
import { useState, useEffect, useCallback } from 'react'
export default function useFetch(url, options, { immediate }) {
const [data, setData] = useState(null)
const [error, setError] = useState(null)
const [isPending, setIsPending] = useState(false)
const executeFetch = useCallback(async () => {
setIsPending(true)
setData(null)
setError(null)
await fetch(url, options)
.then((response) => response.json())
.then((response) => setData(response))
.catch((err) => setError(err))
.finally(() => setIsPending(false))
return { data, error, isPending }
}, [url, options, data, error, isPending])
useEffect(() => {
if (immediate) {
executeFetch()
}
}, [executeFetch, immediate])
return { data, error, isPending, executeFetch }
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我想在提交函数中使用它,而钩子在其他函数中不起作用,就像这样(为简洁起见,代码的简化版本):
export default function SignupModal({ closeModal }) {
const { executeFetch } = useFetch(url, {options},
{ immediate: false }
)
async function handleSubmit(evt) {
evt.preventDefault()
const { data, error, isPending } = await executeFetch()
}
...
}
Run Code Online (Sandbox Code Playgroud)
目前我故意在调用中抛出错误,但错误变量仍然是null
.
我在这里缺少什么?这甚至可以用钩子实现吗?
提前致谢!
React hook 只能用在你的组件体中,不能用在另一个函数中。executeFetch
本身正在返回{ data, error, isPending }
,这使它成为一个嵌套的钩子,所以你不能在你的 handleSubmit 中使用它。
useFetch
已经返回,{ data, error, isPending, executeFetch }
因此 executeFetch 不需要再次返回。您可以从 useFetch 挂钩访问所有这些数据。当您在组件中调用 executeFetch 数据时,数据、错误和 isPending 将被更新,setState
这将导致您的钩子为这些更新的任何值返回一组新值。
export default function useFetch(url, options, { immediate }) {
const [data, setData] = useState(null)
const [error, setError] = useState(null)
const [isPending, setIsPending] = useState(false)
const executeFetch = useCallback(async () => {
setIsPending(true)
setData(null)
setError(null)
await fetch(url, options)
.then((response) => response.json())
.then((response) => setData(response))
.catch((err) => setError(err))
.finally(() => setIsPending(false))
}, [url, options, data, error, isPending])
useEffect(() => {
if (immediate) {
executeFetch()
}
}, [executeFetch, immediate])
return { data, error, isPending, executeFetch }
}
Run Code Online (Sandbox Code Playgroud)
export default function SignupModal({ closeModal }) {
const { executeFetch, data, error, isPending } = useFetch(url, {options},
{ immediate: false }
)
async function handleSubmit(evt) {
evt.preventDefault()
await executeFetch()
}
...
// Example in your return function
{error != null && <Error />}
<Button state={isPending ? 'processing' : 'normal'}
}
Run Code Online (Sandbox Code Playgroud)
根据评论更新
如果您需要访问 handleSubmit 函数中的数据或错误,则需要在钩子中返回承诺的响应/错误,这样您也应该能够访问 handleSubmit 中的数据/错误。
此外,我建议在用户触发 handleSubmit 之前将可能会更改的选项或任何其他变量数据作为参数传递给 executeFetch,以便 executeFetch 始终可以获取最新数据。
const useFetch = url => {
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);
const [data, setData] = useState(null);
const executeFetch = useCallback(
// Here you will access to the latest updated options.
async ({ options }) => {
setIsPending(true);
setError(null);
return await fetch(url, options)
.then(response => response.json())
.then(response => {
setData(response);
return response;
})
.catch(err => {
setError(err.message)
return err;
})
.finally(() => setIsPending(false));
},
[url, setIsPending, setError]
);
return { data, error, isPending, executeFetch }
};
Run Code Online (Sandbox Code Playgroud)
const { data, executeFetch, error, isPending } = useFetch("URL");
const handleSubmit = useCallback(async (event) => {
event.preventDefault();
// I am passing hardcoded { id: 1 } as an argument. This can
// be a value from the state ~ user's input depending on your
// application's logic.
await executeFetch({ id: 1 }).then(response => {
// Here you will access to
// data or error from promise.
console.log('RESPONSE: ', response);
})
}, [executeFetch]);
Run Code Online (Sandbox Code Playgroud)
另一个建议是不要在钩子内立即传递布尔值来触发 executeFetch,由调用者决定是否立即运行 executeFetch。
const { executeFetch, ... } = useFetch(....);
// you can call it immediately after setting the hook if you ever needed
await executeFetch()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
761 次 |
最近记录: |