React async/承诺不解决



react中的异步等待方法有问题。我想在点击按钮后运行异步函数,它可以工作,但看起来有时promise不会得到正确解决。这似乎是典型的等待/异步/然后问题。我从来没有真正在react中使用过它,所以我在这里的知识几乎不存在。

这是我的主要代码。它将状态设置为url,并在单击按钮后执行api调用。它70%的时间都有效。

import { useApi } from "../../services/UrlShortener/useApi";
import { shortenUrl } from "../../services/UrlShortener/UrlShortenerService";
export const Index = () => {
const [url, setUrl] = useState("");
const [shortenedUrl, setShortenedUrl] = useState("");
const getShortUrl = useApi(shortenUrl);
const getShortenedUrl = async () => {
if (url) {
await getShortUrl
.request(url) //request is promise.
.then(() => setShortenedUrl(getShortUrl.data?.value));
// console.log(shortenedUrl);
//setShortenedUrl(getShortUrl.data.value);
} else console.log("error");
console.log(getShortUrl);
};
return (
<>
<button
className="index__shortener__button"
onClick={() => getShortenedUrl()}
>
<BiCut size="2em" />{" "}
<span className="index__shortener__text"> Shorten URL</span>
</button>
<input
className="index__shortener__input"
type="text"
placeholder="Enter your original URL eg.http://interia.pl/news/nie_uwierzysz"
required
onChange={(e) => setUrl(e.target.value)}
/>
<p className="index__shortener__shortener_link">
<a aria-label={shortenedUrl} href={shortenedUrl}>
{shortenedUrl}
</a>
</p>
</>
);
};

其中useApi是可重用钩子,shortenUrl是对api:的调用

export const shortenUrl = async (url) => await axios.post(`${SERVICE_API_URL}`, { value: url});

用于获取数据的典型可重用钩子。

export const useApi = (apiFunc) => {
const request = async (...args) => {
const [data, setData] = useState(null);
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const request = async (...args) => {
setLoading(true);
try {
const result = await apiFunc(...args);
setData(result.data);
} catch (err) {
setError(err.message || "Unexpected Error!");
} finally {
setLoading(false);
}
};
return {
data, //data from api
error,
loading,
request //axios promise function
};

我看到数据有时是空的/未定义的,并试图弄清楚它是如何工作的。

//@Konrad Linkowski approach, sadly arg will be undefined here always because i'm using internal state for useApi
await getShortUrl.request(url)
.then((a)=>{
console.log('getShortUrl', getShortUrl);
console.log("arg",a);
setShortenedUrl(a.data?.value);
})
import { useApi } from "../../services/UrlShortener/useApi";
import { shortenUrl } from "../../services/UrlShortener/UrlShortenerService";
export const Index = () => {
const [url, setUrl] = useState("");
// get request and data from useApi, rename data to shortenedUrl for convenience
// shortenedUrl will update automatically after request is called
const { request, data: shortenedUrl } = useApi(shortenUrl);
const getShortenedUrl = () => {
if (url) {
// this request function returns a promise, but this promise doesn't do anything, so no need to await
request()
} else {
console.log("error");
}
};
// ...
};

正确的方法

看起来你的CCD_2返回了一个承诺,但没有对它做任何事情。

在react中执行此操作的正确方法只是等待状态更新:

PD_7

最新更新