构建您自己的 Hook 以将图像上传到 Firebase
让我们开始吧
在开始构建自定义 React Hook 之前,我想提醒你,你应该对 React Hook 的基本知识有充分的了解。如果你不熟悉这些基础知识,可以从这里开始,然后再回到这里。
让我们开始吧
为了构建自定义钩子,您应该记住以下几点...请在此处阅读所有规则。
现在我们已经介绍了基础知识并准备构建我们自己的自定义 Hook。
我们将构建一个自定义钩子,它将以文件作为道具并将其上传到 Firebase 存储,同时返回上传进度,最后返回可存储在数据库中或用作 img src 的公共 URL。
创建 React 项目
创建你的 React 项目并进入项目目录
npx create-react-app <your app name here>
cd <your app name here>
然后启动你的反应应用程序
npm run start
现在您应该有一个如下所示的样板 React 项目。
清理并开始构建 UI
清理后,您的文件结构如下所示
清理所有样板代码并添加一个带有文件类型输入的表单,App.js
并添加方法handleChange
来处理用户选择文件时的事件。App.js
添加这些东西之后......
import React, { useState } from "react";
import "./App.css";
function App() {
const [file, setFile] = useState(null);
const [error, setError] = useState(null);
const types = ["image/png", "image/jpeg", "image/jpg"];
const handleChange = (e) => {
let selectedFile = e.target.files[0];
if (selectedFile) {
if (types.includes(selectedFile.type)) {
setError(null);
setFile(selectedFile);
} else {
setFile(null);
setError("Please select an image file (png or jpg)");
}
}
};
return (
<div className="App">
<form>
<label>
<input type="file" onChange={handleChange} />
<span>Upload Image</span>
</label>
</form>
</div>
);
}
export default App;
我还添加了一个仅接受图像文件的过滤器,并使用useState
钩子将所选文件的file
状态和所有错误error
状态存储在其中。
现在你的应用应该看起来像这样……
创建 Firebase 项目
转到Firebase 控制台并使用您的 Google 帐户登录,然后单击添加项目
然后给你的项目命名并继续
禁用谷歌分析并创建项目
使用 Firebase 注册您的应用
将您的应用添加到 Firebase。
为您的应用命名并注册。Firebase 将为您提供该应用的凭据,其内容类似于以下对象。
var firebaseConfig = {
apiKey: "AIzaSyDo5UUe86THOjczUAhytr7yu67FlLVmpj2E",
authDomain: "new-project.firebaseapp.com",
databaseURL: "https://new-project.firebaseio.com",
projectId: "new-project",
storageBucket: "new-project.appspot.com",
messagingSenderId: "509872254322",
appId: "1:509872254322:web:d63d977d86c734nu829e12f"
};
复制 firebase 给您的对象,然后转到您的项目目录。
将您的应用与 Firebase 连接
firebase
在文件夹内创建一个新文件夹并命名。在文件夹内src
创建一个文件,并将对象粘贴到文件中。config.js
firebase
firebaseConfig
现在安装firebase
npm 包。从根目录执行以下命令。
npm i firebase
现在通过在config.js
文件中导入 firebase 包并导出storage
方法来初始化 firebase。
import firebase from "firebase";
import "firebase/storage";
const firebaseConfig = {
apiKey: "AIzaSyDo5UUe86THOjczUAhytr7yu67FlLVmpj2E",
authDomain: "new-project.firebaseapp.com",
databaseURL: "https://new-project.firebaseio.com",
projectId: "new-project",
storageBucket: "new-project.appspot.com",
messagingSenderId: "509872254322",
appId: "1:509872254322:web:d63d977d86c734nu829e12f"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const projectStorage = firebase.storage();
export { projectStorage };
在 Firebase 控制台中设置存储
单击左侧栏中的“存储”链接,然后单击“开始”
然后单击下一步并完成。
现在我们需要更改,rules
以便每个人都可以从您的 Firebase 存储中read
访问。 为此,请导航至“规则”选项卡。write
然后删除当前规则,并将以下规则粘贴到规则编辑器中。然后确认Publish
新规则正确无误。
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
现在我们已经准备好将图像从我们的应用程序上传到 Firebase。
最后让我们创建自定义钩子
src
在文件夹名称中创建一个新文件夹。然后在文件夹中hooks
创建一个新文件。这将是我们用于将图像上传到 Firebase 存储的自定义钩子。useStorage.js
hooks
最终的文件夹结构将如下所示。
我们将使用两个基本钩子useState
和useEffect
我们的自定义钩子。
- 我们需要创建一个,并在我们的文件
reference to the Firebase storage
中初始化和导出它。config.js
- 然后使用
put()
该参考上的方法上传图像。 - 该方法会在每次状态变化时
put()
返回一个快照。我们可以使用此快照来跟踪上传进度(以百分比表示) 。snap
- 最后,我们将从上传的图像中获取公共 URL。
因此在文件中添加以下代码useStorage.js
。
import { useState, useEffect } from "react";
import { projectStorage } from "../firebase/config";
export const useStorage = (file) => {
const [progress, setProgress] = useState(0);
const [error, setError] = useState(null);
const [url, setUrl] = useState(null);
// runs every time the file value changes
useEffect(() => {
if (file) {
// storage ref
const storageRef = projectStorage.ref(file.name);
storageRef.put(file).on(
"state_changed",
(snap) => {
// track the upload progress
let percentage =
Math.round(
(snap.bytesTransferred / snap.totalBytes) * 100
);
setProgress(percentage);
},
(err) => {
setError(err);
},
async () => {
// get the public download img url
const downloadUrl = await storageRef.getDownloadURL();
// save the url to local state
setUrl(downloadUrl);
}
);
}
}, [file]);
return { progress, url, error };
};
我们在钩子中添加了所有逻辑useEffect
,并将其添加file
为依赖项。这样,每当文件发生更改时,我们的钩子就会重新运行。
最后,我们导出了progress
、url
和error
。
将钩子集成到我们的组件中
useStorage
现在,我们可以在组件中导入该钩子,并将其与所选文件一起使用。集成该钩子后,
我们还可以显示进度。App.js
useStorage
import React, { useState } from "react";
import "./App.css";
import { useStorage } from "./hooks/useStorage";
function App() {
const [file, setFile] = useState(null);
const [error, setError] = useState(null);
const types = ["image/png", "image/jpeg", "image/jpg"];
const handleChange = (e) => {
let selectedFile = e.target.files[0];
if (selectedFile) {
if (types.includes(selectedFile.type)) {
setError(null);
setFile(selectedFile);
} else {
setFile(null);
setError("Please select an image file (png or jpg)");
}
}
};
// Getting the progress and url from the hook
const { progress, url } = useStorage(file);
return (
<div className="App">
<form>
<label>
<input type="file" onChange={handleChange} />
<span>Upload Image</span>
</label>
</form>
{error && <p>{error}</p>}
</div>
);
}
export default App;
现在我们可以访问文件的progress
and了。我们可以用它来给用户一些反馈,然后在上传完成时url
显示图片。在显示错误的段落标签之后的根目录下 添加这些内容。 现在我们的应用也会显示进度和图片了。url
html
div
{file && <p>{progress}% uploaded</p>}
{url && (
<p>
<b>File url: </b>
<a href={url}>{url}</a>
</p>
)}
{url && <img src={url}></img>}
我们App.js
现在...
import React, { useState } from "react";
import "./App.css";
import { useStorage } from "./hooks/useStorage";
function App() {
const [file, setFile] = useState(null);
const [error, setError] = useState(null);
const types = ["image/png", "image/jpeg", "image/jpg"];
const handleChange = (e) => {
let selectedFile = e.target.files[0];
if (selectedFile) {
if (types.includes(selectedFile.type)) {
setError(null);
setFile(selectedFile);
} else {
setFile(null);
setError("Please select an image file (png or jpg)");
}
}
};
// Getting the progress and url from the hook
const { progress, url } = useStorage(file);
return (
<div className="App">
<form>
<label>
<input type="file" onChange={handleChange} />
<span>Upload Image</span>
</label>
</form>
{error && <p>{error}</p>}
{file && <p>{progress}% uploaded</p>}
{url && (
<p>
<b>File url: </b>
<a href={url}>{url}</a>
</p>
)}
{url && <img src={url}></img>}
</div>
);
}
export default App;
- 所以现在我们已经成功创建了自己的自定义钩子。
- 将其集成到我们的组件中。
- 并且还显示进度并在上传完成后显示图像。
- 如果需要,您还可以将 URL 存储在数据库中。
您可以在这里实时查看该应用。快去看看吧。
你也可以在我的Github Reposource code
中查看完整代码。使用代码前请确保将其替换为。否则将无法使用。my firebase credentials
your credentials
在网络上找到我🕸:
- 💻访问我的网站
- 🌟 查看我的Substack
- 😸 在 GitHub 上查看我的Repos
- 🦊 在 GitLab 上查看我的仓库
- 📦 在 NPM 上检查我的软件包
- 🔗在 LinkedIn 上查看我的个人资料
- 📝在 Dev.to 上查看我的博客
- 😜 在Instagram上关注我
- 📚 查看我的Goodreads 个人资料
- 📪在这里联系我