如何在单击时添加用户输入?
自学成才的编码员。希望我能充分解释这一点。用户通过输入菜肴名称,食物类别,封面IMG等等值来创建食谱烹饪指南。步骤阵列目前只有1个步骤。我想要一个用户可以单击的按钮,将另一个“步骤”和“ gif”添加到步骤数组中。谁能提出一种方法,当用户单击“添加步骤”按钮时,在屏幕上有另一组“步骤”和“ IMG”渲染?我有一个handleaddsteps功能,没有内部。有人推荐使用DOM吗?只想知道这是否是在错误的兔子洞中投入时间之前的好方法。谢谢您的任何建议。
import React from "react";
import { useState, useEffect } from "react";
// Styles
import "./UploadGuide.scss";
// Firebase
import { doc, setDoc } from "firebase/firestore";
import { db, storage } from "../../firebase";
import { v4 as uuidv4 } from "uuid";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
function UploadGuide() {
const [file, setFile] = useState("");
const [data, setData] = useState({});
const [percentage, setPercentage] = useState(null);
// const [stepsCounter, setStepsCounter] = useState(0);
// Upload IMG
useEffect(() => {
const uploadFile = () => {
const name = new Date().getTime() + file.name;
const storageRef = ref(storage, file.name);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log("Upload is " + progress + "% done");
setPercentage(progress);
switch (snapshot.state) {
case "paused":
console.log("Upload is paused");
break;
case "running":
console.log("Upload is running");
break;
default:
break;
}
},
(error) => {
console.log(error);
},
() => {
// Handle successful uploads on complete
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setData((prev) => ({ ...prev, img: downloadURL }));
});
}
);
};
file && uploadFile();
}, [file]);
console.log(file);
console.log(data);
// When user clicks Add Steps button, page renders another steps card
const handleAddSteps = () => {};
// When user submits guide, upload data to firecloud db and imgs to firebase storage.
const handleAddGuide = async (e) => {
e.preventDefault();
const newId = uuidv4();
// const stepsArray = []
await setDoc(doc(db, "guides", newId), {
author: e.target.author.value,
categoryId: "100",
categoryName: e.target.categoryName.value,
coverGif: data.img,
id: newId,
name: e.target.name.value,
tags: e.target.tags.value,
// steps: stepsArray
steps: [
{
step: e.target.step.value,
gif: data.img,
},
],
});
};
return (
<div className="upload">
<form onSubmit={handleAddGuide} className="upload__form">
<div className="upload__card">
<div className="upload__inputs">
<label className="upload__label">Guide Name</label>
<input
className="upload__input"
placeholder="Name of your recipe"
type="name"
name="name"
// value=""
></input>
</div>
<div className="upload__inputs">
<label className="upload__label">Author</label>
<input
className="upload__input"
type="author"
name="author"
></input>
</div>
<div className="upload__inputs">
<label className="upload__label">Category</label>
<select
name="categoryName"
className="upload__input"
defaultValue={"Cooking"}
>
<option value="Cooking">Cooking</option>
<option></option>
</select>
</div>
<div className="upload__inputs">
<label className="upload__label">Tags</label>
<input
name="tags"
className="upload__input upload__input--large"
placeholder="Add relevant tags to help people find your guide"
></input>
</div>
</div>
<div className="upload__card upload__card--addstep">
<div className="upload__inputs">
<label className="upload__label">Step 1</label>
<input
className="upload__input upload__input--large"
name="step"
></input>
</div>
<div className="upload__inputs">
<div>
<img src={file ? URL.createObjectURL(file) : ""}></img>
</div>
<label
htmlFor="file"
style={{ cursor: "pointer" }}
className="upload__add"
>
+ IMG
</label>
<input
id="file"
onChange={(e) => setFile(e.target.files[0])}
style={{ display: "none" }}
type="file"
></input>
</div>
</div>
<div className="upload__box">
<button
className="upload__add"
onClick={handleAddSteps}
style={{ cursor: "pointer" }}
>
Add Step
</button>
</div>
<div className="upload__cta">
<button
disabled={percentage !== null && percentage < 100}
type="submit"
className="upload__submit"
style={{ cursor: "pointer" }}
>
Upload
</button>
</div>
</form>
</div>
);
}
export default UploadGuide;
这是页面外观的图像: 在此处输入图像描述
如果我缺少任何关键信息,请让我知道。任何建议将不胜感激。谢谢。
Self taught coder. Hopefully I can explain this adequately. Users create recipe cooking guides by inputing values like dish name, food category, cover img, etc. The steps array only has 1 step at the moment. I want a button that users can click that would add another "step" and "gif" to the steps array. Can anyone suggest a method to have another set of "step" and "img" render on screen when the user clicks the Add Step button? I have a handleAddSteps function with nothing inside. Somebody recommended using DOM? Just want to know if this is a good way to go before investing time down the wrong rabbit hole. Thank you kindly for any advice.
import React from "react";
import { useState, useEffect } from "react";
// Styles
import "./UploadGuide.scss";
// Firebase
import { doc, setDoc } from "firebase/firestore";
import { db, storage } from "../../firebase";
import { v4 as uuidv4 } from "uuid";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
function UploadGuide() {
const [file, setFile] = useState("");
const [data, setData] = useState({});
const [percentage, setPercentage] = useState(null);
// const [stepsCounter, setStepsCounter] = useState(0);
// Upload IMG
useEffect(() => {
const uploadFile = () => {
const name = new Date().getTime() + file.name;
const storageRef = ref(storage, file.name);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log("Upload is " + progress + "% done");
setPercentage(progress);
switch (snapshot.state) {
case "paused":
console.log("Upload is paused");
break;
case "running":
console.log("Upload is running");
break;
default:
break;
}
},
(error) => {
console.log(error);
},
() => {
// Handle successful uploads on complete
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setData((prev) => ({ ...prev, img: downloadURL }));
});
}
);
};
file && uploadFile();
}, [file]);
console.log(file);
console.log(data);
// When user clicks Add Steps button, page renders another steps card
const handleAddSteps = () => {};
// When user submits guide, upload data to firecloud db and imgs to firebase storage.
const handleAddGuide = async (e) => {
e.preventDefault();
const newId = uuidv4();
// const stepsArray = []
await setDoc(doc(db, "guides", newId), {
author: e.target.author.value,
categoryId: "100",
categoryName: e.target.categoryName.value,
coverGif: data.img,
id: newId,
name: e.target.name.value,
tags: e.target.tags.value,
// steps: stepsArray
steps: [
{
step: e.target.step.value,
gif: data.img,
},
],
});
};
return (
<div className="upload">
<form onSubmit={handleAddGuide} className="upload__form">
<div className="upload__card">
<div className="upload__inputs">
<label className="upload__label">Guide Name</label>
<input
className="upload__input"
placeholder="Name of your recipe"
type="name"
name="name"
// value=""
></input>
</div>
<div className="upload__inputs">
<label className="upload__label">Author</label>
<input
className="upload__input"
type="author"
name="author"
></input>
</div>
<div className="upload__inputs">
<label className="upload__label">Category</label>
<select
name="categoryName"
className="upload__input"
defaultValue={"Cooking"}
>
<option value="Cooking">Cooking</option>
<option></option>
</select>
</div>
<div className="upload__inputs">
<label className="upload__label">Tags</label>
<input
name="tags"
className="upload__input upload__input--large"
placeholder="Add relevant tags to help people find your guide"
></input>
</div>
</div>
<div className="upload__card upload__card--addstep">
<div className="upload__inputs">
<label className="upload__label">Step 1</label>
<input
className="upload__input upload__input--large"
name="step"
></input>
</div>
<div className="upload__inputs">
<div>
<img src={file ? URL.createObjectURL(file) : ""}></img>
</div>
<label
htmlFor="file"
style={{ cursor: "pointer" }}
className="upload__add"
>
+ IMG
</label>
<input
id="file"
onChange={(e) => setFile(e.target.files[0])}
style={{ display: "none" }}
type="file"
></input>
</div>
</div>
<div className="upload__box">
<button
className="upload__add"
onClick={handleAddSteps}
style={{ cursor: "pointer" }}
>
Add Step
</button>
</div>
<div className="upload__cta">
<button
disabled={percentage !== null && percentage < 100}
type="submit"
className="upload__submit"
style={{ cursor: "pointer" }}
>
Upload
</button>
</div>
</form>
</div>
);
}
export default UploadGuide;
Here is an image of what the page looks like:
enter image description here
Please let me know if I'm missing any key information. Any advice is appreciated. Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于每个指南都可以有多个步骤,因此我宁愿创建一个处理多个步骤对象数组的状态,而不仅仅是计数器。
这样,您可以在数组中渲染尽可能多的步骤。
然后,添加步骤只是将对象(带有空状态)添加到该数组的问题。
我做了这个功能型的例子,应该足够清楚以表明我的意思:
Since each Guide can have multiple steps, I would rather create a state that handles an array of multiple step objects, than just a counter.
With this, you can render as much steps as you have in the array.
Then, adding steps just will be a matter of adding objects (with an empty state) to that array.
I made this functional example, that should be clear enough to show what I mean: