[英]Custom Hook to Load Firebase Image URL
I'm trying to create a custom hook that will load the URL for an image stored in Firebase.我正在尝试创建一个自定义挂钩,它将为存储在 Firebase 中的图像加载 URL。
So far I've arrived at the following:到目前为止,我已经得出以下结论:
useLoadImageURL.js使用LoadImageURL.js
export default async function useLoadImageURL(projectId, fileName) {
const [url, setURL] = useState()
useEffect(() => {
return url
}, [url])
const storage = getStorage(app);
setURL(await getDownloadURL(ref(storage, `images/projects/${projectId}/${fileName}`)))
}
However, when I use it in my component, I only get promises, and therefore using the returned promise as URL does not work.但是,当我在我的组件中使用它时,我只会得到承诺,因此将返回的 promise 用作 URL 是行不通的。
I'm calling the hook via the following:我通过以下方式调用挂钩:
ProjectCard.js ProjectCard.js
export default function ProjectCard({ project }) {
const coverImageURL = useLoadImageURL(project.id, project.coverImagePath)
return <img src={coverImageURL} />
}
How can I change the hook or how I'm calling it to retrieve the actual URL?如何更改挂钩或如何调用它来检索实际的 URL?
You can remove async
and await
from your code, and instead of calling setUrl
at the bottom of your hook -- which would initiate the call every time the callee component rerenders -- wrap it in a useEffect
, and update the state in a then
callback.您可以从代码中删除
async
和await
,而不是在挂钩底部调用setUrl
- 每次被调用方组件重新呈现时都会启动调用 - 将其包装在useEffect
中,并在then
回调中更新 state .
edit: Full code:编辑:完整代码:
const storage = getStorage(app); // as app seems to be external to the hook, storage can likely be too
export default function useLoadImageURL(projectId, fileName) {
const [url, setUrl] = useState();
useEffect(() => {
getDownloadURL(ref(storage, `images/projects/${projectId}/${fileName}`))
.then((value) => {
setUrl(value); // should work provided getDownloadURL actually is a promise that gives a string
});
}, [projectId,fileName]);
return url;
}
This will make the url
state only change when projectId
or fileName
changes.这将使
url
state 仅在projectId
或fileName
更改时更改。
You have to do your side effect logic (awaiting async response in your case) inside the useEffect
hook.您必须在
useEffect
挂钩内执行副作用逻辑(在您的情况下等待异步响应)。
Following your intent to do it with promises and async
await
, your snippet hook should be something like this.按照您使用 promises 和
async
await
来完成的意图,您的代码片段挂钩应该是这样的。
import { useState, useEffect } from "react";
// hook
function useLoadImageURL(filename) {
const [url, setURL] = useState("some-image-spinner-url");
// simulating your async api call to firebase service
const setTimeoutAsync = (cb, delay) =>
new Promise((resolve) => {
setTimeout(() => {
resolve(cb());
}, delay);
});
useEffect(() => {
async function asyncFn() {
const url = await setTimeoutAsync(() => filename, 3000);
setURL(url);
}
asyncFn();
}, [filename]);
return [url];
}
// main component
function App() {
const [url] = useLoadImageURL("firebase-file-name-f1");
return <div> {url} </div>;
}
export default App;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.