将表单提交到 firestore 后清除表单输入字段吗?

发布于 2025-01-11 16:13:30 字数 1567 浏览 0 评论 0原文

我正在尝试使用 React 和 Firestore 创建一个简单的 CRUD 应用程序(两者都是新的)。 我从未使用过react with db,所以以前我只是在提交后将标题和内容的状态设置为“”,但这会使用Firestore onSnapshot 创建一个循环。我可以将它包装在表单中并使用 PreventDefault(),但是(可能是我的错误)除非我留下了异步,否则它会产生奇怪的结果。我想了几天这个问题,但还没有找到正确的答案。也许我可以阻止 Firestore 接受并保存空字符串?这不可能是一个合理的答案,因为除了我的缺点之外,它会从前到后创建一个额外的循环。我认为答案应该是某种有条件的状态设置,但这又只是一个猜测。现在我在 youtube 上看了好几个小时的教程,但他们都忽略了这个问题,我认为这有点愚蠢。我想找到它的答案,因为即使我可能会想出一些可行的东西,但我真的很喜欢看到它的常见用例,这肯定会比我的试错解决方案更优雅。先感谢您!

function App() {

  const [newTitle, setNewTitle] = useState("")
  const [newContent, setNewContent] = useState("")
  const [users, setUsers] = useState([]);

  const usersCollectionRef = collection(db, "users")

  useEffect(
    () =>
      onSnapshot(collection(db, "users"), (snapshot) =>
        setUsers(snapshot.docs.map((doc) => ({ ...doc.data(), id: doc.id })))
      ),
    []
  );

  const createEntry = async () => {
        await addDoc(usersCollectionRef, { Title: newTitle, Content: newContent })
  }

  return (

    <div>
        <input type="text" placeholder="Title" onChange={event => { setNewTitle(event.target.value)} }/>
        <textarea type="text" placeholder="Content" onChange={event => { setNewContent(event.target.value) } }/> 
        <button onClick={createEntry}> Add </button>

       {users.map((user) => {
        return (
          <div className="note">
            <h1> {user.Title} </h1>
            <p>{user.Content}</p>
          </div>
        )
      })}
    </div>
  );
}

I'm trying to create a simple CRUD application with react and Firestore (new to both).
I never used react with db, so previously I would simply set the state of title and content to "" after submit, but that's create a loop with Firestore onSnapshot. I could wrap it in form and use preventDefault(), but (possibly my mistake) it created strange outcome unless I left behind async. I'm thinking about this issue for a few days and yet to find the right answer to it. Maybe I could prevent Firestore to accept and save empty strings? That cant be a reasonable answer as it would create an extra loop front to back for no other reason than my shortcoming. I think the answer should be some sort of a conditionally state setting, but that's just a guess again. Now I`ve watched quite a few hours a tutorials on youtube, but they all leave out this issue, which I think its a bit silly. I would like to find the answer to it as even though I might could come up with something that will work, but I really like to see the common use case of it which defo will be more elegant than my trial and error solution. Thank you in advance!

function App() {

  const [newTitle, setNewTitle] = useState("")
  const [newContent, setNewContent] = useState("")
  const [users, setUsers] = useState([]);

  const usersCollectionRef = collection(db, "users")

  useEffect(
    () =>
      onSnapshot(collection(db, "users"), (snapshot) =>
        setUsers(snapshot.docs.map((doc) => ({ ...doc.data(), id: doc.id })))
      ),
    []
  );

  const createEntry = async () => {
        await addDoc(usersCollectionRef, { Title: newTitle, Content: newContent })
  }

  return (

    <div>
        <input type="text" placeholder="Title" onChange={event => { setNewTitle(event.target.value)} }/>
        <textarea type="text" placeholder="Content" onChange={event => { setNewContent(event.target.value) } }/> 
        <button onClick={createEntry}> Add </button>

       {users.map((user) => {
        return (
          <div className="note">
            <h1> {user.Title} </h1>
            <p>{user.Content}</p>
          </div>
        )
      })}
    </div>
  );
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心奴独伤 2025-01-18 16:13:30

我花了很长时间才弄清楚自己做错了什么,但似乎我终于克服了它。现在我对我的回答持保留态度,因为我希望它对你有帮助,但可能并不是我所有的“理论”都是100%正确的。 (PS:将用户更改为注释,因为它更有意义)

在我学习时,我记得一个与此完全相同的项目,但没有 firestore 后端。我重用了该项目并进行了大量的试验和错误来找到解决方案。

我确实记得在那个项目中它被分解为组件,我们将相关信息传回 app.jsx。但当我思考的时候,我意识到我们实际上做了更多的事情。
我认为可能是我在这里使用了 3 个不同状态的问题。

const [newTitle, setNewTitle] = useState("")
const [newContent, setNewContent] = useState("")
const [users, setUsers] = useState([]);

现在一切都很好而且很实用,但我相信不受控制?现在,我们在上一个项目中所做的实际上是将各个用户条目存储在对象中,并将 id 传回 app.js。当我们这样做时,我们将对象字段的状态重置为“”。

 const [note, setNote] = useState({
       title:"",
       content:""
    });

我认为这可能是现在我们在数组中拥有对象而不是看似彼此不相关的单个字符串起作用的原因。 ?这是我的猜测。

app.jsx

const [notes, setNotes] = useState([]);

const usersCollectionRef = collection(db, "notes")

const createEntry = async (note) => {
        await addDoc(usersCollectionRef, { title: note.title, content: note.content })
  }

 return (
    <div>      
    <CreateArea onAdd={createEntry} />
      {notes.map((noteItem) => {
        return (
          <Note
            key={noteItem.id}
            id={noteItem.id}
            title={noteItem.title}
            content={noteItem.content}
            onDelete={deleteNote}
          />
        );
      })}
    </div>
  );
}

createArea.jsx

function CreateArea(props) {
  const [note, setNote] = useState({
    title: "",
    content: ""
  });

  function handleChange(event) {
    const { name, value } = event.target;

    setNote(prevNote => {
      return {
        ...prevNote,
        [name]: value
      };
    });
  }

  function submitNote(event) {
    props.onAdd(note);
    setNote({
      title: "",
      content: ""
    });
    event.preventDefault();
  }

  return (
    <div className="create-area">
      <form>
        <input
          name="title"
          onChange={handleChange}
          value={note.title}
          placeholder="Title"
        />
        <textarea
          name="content"
          onChange={handleChange}
          value={note.content}
          placeholder="Take a note..."
          rows="3"
        />
        <button onClick={submitNote}>Add</button>
      </form>
    </div>
  );
}

通过这样做,我使用扩展运算符来处理值更改,并且在提交之前它不会重置为“”。我认为问题可能在于 i 最初需要 3 个状态来执行此操作。

  • 第一个状态:“”
  • 第二个状态:处理输入更改
  • 第三个状态:提交并将值重置为“”

用我的原始状态执行此操作在逻辑上是不可能的,我认为所以需要一个额外的步骤。提交后,它会发回注释,我们可以访问其字段来保存它。对于某些人来说这可能不是什么大问题,但我很高兴我自己找到了解决方案,尽管我花了比我预期更长的时间。我希望它对某人有帮助。请注意,所有为什么它不起作用的“想法”都只是想法。如果您有什么要补充或者纠正的,非常欢迎!谢谢你!

Took me forever to figure out what Im doing wrong, but seems like it finally I overcome it. Now took my answer with a pinch of salt as Im hoping it will be helpful for you, but might not all my "theories" will be 100% correct. (PS: changed users to notes as it makes a lot more sense)

While I was studying I remembered a project which exactly the same as this, but without firestore backend. I reused that project and done a lot of trial and error to find the solution.

I did remember that on that project it was broken down to components and we passed back the relevant info to the app.jsx. But while i was thinking i realised that we actually done more than that.
I think might be the issue that here I used 3 different states.

const [newTitle, setNewTitle] = useState("")
const [newContent, setNewContent] = useState("")
const [users, setUsers] = useState([]);

Now its all nice and functional, but uncontrolled I believe? Now what we have done in the previous project that we actually stored the individual user entries in and object and passed back the id`s to the app.js. While we were doing it we reset the state of the object fields to "".

 const [note, setNote] = useState({
       title:"",
       content:""
    });

I think might be the reason for this to work now that we have objects in an array, not individual strings seemingly not related to each other. ? Its a guess from my side.

app.jsx

const [notes, setNotes] = useState([]);

const usersCollectionRef = collection(db, "notes")

const createEntry = async (note) => {
        await addDoc(usersCollectionRef, { title: note.title, content: note.content })
  }

 return (
    <div>      
    <CreateArea onAdd={createEntry} />
      {notes.map((noteItem) => {
        return (
          <Note
            key={noteItem.id}
            id={noteItem.id}
            title={noteItem.title}
            content={noteItem.content}
            onDelete={deleteNote}
          />
        );
      })}
    </div>
  );
}

createArea.jsx

function CreateArea(props) {
  const [note, setNote] = useState({
    title: "",
    content: ""
  });

  function handleChange(event) {
    const { name, value } = event.target;

    setNote(prevNote => {
      return {
        ...prevNote,
        [name]: value
      };
    });
  }

  function submitNote(event) {
    props.onAdd(note);
    setNote({
      title: "",
      content: ""
    });
    event.preventDefault();
  }

  return (
    <div className="create-area">
      <form>
        <input
          name="title"
          onChange={handleChange}
          value={note.title}
          placeholder="Title"
        />
        <textarea
          name="content"
          onChange={handleChange}
          value={note.content}
          placeholder="Take a note..."
          rows="3"
        />
        <button onClick={submitNote}>Add</button>
      </form>
    </div>
  );
}

By doing this I use the spread operator to handle the value changes and until it is submitted it wont be reset to "". I think the issue might have been that the i would have needed 3 state to do this initially.

  • first state: ""
  • second state: handles the input changes
  • third state: submitting and reset value to ""

Doing this with my original states wouldnt be logically possible i think so one extra step needed. On submission it sends back the note where we have access to its fields to save it. Its probably not a biggie for some, but Im happy that i find solution on my own, although it took me longer than i expected. I hope it can be helpful for someone. Please note that all the "ideas" why it didn`t work are ideas only. If you have anything to add or correct me you are more than welcome to! Thank you!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文