[英]React custom hook is not updating from first click
I've created a custom hook to fetch data with events handlers, when I using it on click event the hook makes the request on the second click我创建了一个自定义挂钩来使用事件处理程序获取数据,当我在单击事件上使用它时,挂钩在第二次单击时发出请求
useFetch.js使用Fetch.js
import { useState, useEffect } from 'react';
import { makeRequest } from '../utils';
const useFetch = (query = {}) => {
const [request, setRequest] = useState({ ...query });
const [data, setData] = useState({
response: null,
isError: null,
isLoading: request.isLoading,
});
const fetchData = async () => {
if (!request.url) {
return;
}
try {
const res = await makeRequest(
request.url,
request.method || 'get',
request.body || null,
);
setData({
response: res,
isLoading: false,
error: null,
});
} catch (error) {
setData({
response: null,
error,
isLoading: false,
});
}
};
const onEvent = (req) => {
if (req) {
setRequest({ ...req });
}
};
useEffect(() => fetchData(), [request]);
return { ...data, onEvent };
};
export default useFetch;
Component File组件文件
const { isLoading, isError, response, onEvent } = useFetch();
const ClickMe = () => {
onEvent({
url: 'v1/profile/login',
method: 'post',
body: {
username: 'eee@ddd.com',
password: '2342332',
},
});
console.log('response', response);
};
return (
<>
<button onClick={() => ClickMe()} type="button">
Click Me
</button>
)
the log inside the ClickMe function is null in the first click but in the second click it returns the value ClickMe function 内的日志在第一次单击时为 null 但在第二次单击时返回值
Because fetchData
is asynchronous function you cannot know when resposne
will be set, that's why you cannot access it like normal sync code因为fetchData
是异步的 function 你不知道什么时候会设置resposne
,这就是为什么你不能像普通同步代码一样访问它
in your app code you could observe response
change to console it like在您的应用程序代码中,您可以观察到response
更改以控制它
useEffect(() => { console.log(response) }, [ response ]);
At the time of console.log, the response is not fetched.在 console.log 的时候,没有获取响应。 Since when ever response
changes, the component re-renders, you can try like below to see the updated values of isLoading
and response
.因为当response
发生变化时,组件会重新渲染,您可以尝试如下所示查看isLoading
和response
的更新值。
return (
<>
{isLoading && <div> Loading... </div>}
{`Resonse is ${JSON.stringify(response)}`}
<button onClick={() => ClickMe()} type="button">
Click Me
</button>
</>
);
As the others said, it's an asynchronous operation.正如其他人所说,这是一个异步操作。 If you want to use the response as soon as you called onEvent, you can do something along these lines using a promise:如果您想在调用 onEvent 后立即使用响应,您可以使用 promise 执行以下操作:
import { useState, useEffect } from 'react';
import { makeRequest } from '../utils';
const useFetch = (query = {}) => {
useEffect(() => {
if (query) {
fetchData(query)
}
}, []) // if query is provided, run query
const [data, setData] = useState({
response: null,
isError: null,
isLoading: true
});
const fetchData = async (query) => {
return new Promise((resolve, reject) => {
if (!query.url) {
reject('url needed')
}
makeRequest(query).then(res => {
setData({
response: res,
isLoading: false,
error: null
})
resolve(res)
).catch(error => {
setData({
response: null,
error,
isLoading: false
});
reject(error)
});
})
})
};
// provide fetchData directly for lazy calls
return { ...data, fetchData };
};
export default useFetch;
And then call it like so:然后这样称呼它:
const { response, fetchData } = useFetch()
fetchData({
url: 'v1/profile/login',
method: 'post',
body: {
username: 'eee@ddd.com',
password: '2342332',
},
}).then(res => ...);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.