如何使用 React 让我的输入在段落中呈现?

How can I get my input to render in a paragraph, using React?

我正在处理待办事项列表,我已经创建了要添加待办事项的功能。呈现待办事项的列表位于我创建 addTodo 函数的单独组件中。一切似乎都很好,但是,当我单击添加待办事项时,我添加的输入不会呈现在我在待办事项组件中创建的段落中。我还安慰了我在输入中添加的数据,它显示在控制台中。我相信我的问题在于我如何在 Todo 组件的段落元素中设置道具。这是我的代码,如果有帮助的话。

import { useState, useEffect } from "react";
import classes from "./addlink.module.css";

import firebase from "firebase/app";
import initFirebase from "../../config";
import "firebase/firestore";

import Todo from "../Todo/Todo";

import { v4 as uuidv4 } from "uuid";

initFirebase();
const db = firebase.firestore();

function AddLink(props) {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState("");

  useEffect(() => {
    db.collection("links")
      .orderBy("timestamp", "desc")
      .onSnapshot((snapshot) => {
        setTodos(
          snapshot.docs.map((doc) => ({
            id: doc.id,
            todo: doc.data().todo,
          }))
        );
      });
  }, []);

  const addTodo = (event) => {
    event.preventDefault();

    db.collection("links").add({
      id: uuidv4(),
      todo: input,
      timestamp: firebase.firestore.FieldValue.serverTimestamp(),
    });
    console.log(input);
    setInput("");
  };

  return (
    <div className={classes.addlink}>
      <form>
        <div className={classes.adminlink}>
          <input
            type="text"
            value={input}
            onChange={(event) => setInput(event.target.value)}
          />
          <button
            className={classes.adminbutton}
            type="submit"
            onClick={addTodo}
          >
            Add new link
          </button>
        </div>
      </form>
      {todos.map((todo, id) => (
        <Todo todo={todo} key={id} />
      ))}
      
    </div>
  );
}

export default AddLink;
 

还有 Todo.js

 import React from "react";
import { AiOutlinePicture } from "react-icons/ai";
import { AiOutlineStar } from "react-icons/ai";
import { GoGraph } from "react-icons/go";
import DeleteForeverIcon from "@material-ui/icons/DeleteForever";

import classes from "./todo.module.css";

import firebase from "firebase/app";
import initFirebase from "../../config";
import "firebase/firestore";

initFirebase();
const db = firebase.firestore();

function Todo(props) {
  const deleteHandler = (event) => {
    db.collection("links").doc(props.todo.id).delete();
  };

  return (
    <li className={classes.adminsection}>
      <div className={classes.linkCards}>
        <h3>Todo</h3>
        <p>{props.value}</p>
        <div>
          <AiOutlinePicture />
          <AiOutlineStar />
          <GoGraph />
          <DeleteForeverIcon onClick={deleteHandler} />
        </div>
      </div>
    </li>
  );
}

export default Todo;

据我所知,您的 todo 对象具有 idtodotimestamp 属性。

const addTodo = (event) => {
  event.preventDefault();

  db.collection("links").add({
    id: uuidv4(),
    todo: input,
    timestamp: firebase.firestore.FieldValue.serverTimestamp(),
  });
  setInput("");
};

links 集合更新时,您将其全部映射到 todo 属性 状态。

useEffect(() => {
  db.collection("links")
    .orderBy("timestamp", "desc")
    .onSnapshot((snapshot) => {
      setTodos(
        snapshot.docs.map((doc) => ({
          id: doc.id,
          todo: doc.data().todo,
        }))
      );
    });
}, []);

你映射它并传递 整个 todo 属性 作为道具。

 {todos.map((todo, id) => (
   <Todo todo={todo} key={id} />
 ))}

最后在 Todo 中你访问了一个 value prop.

<p>{props.value}</p>

这不是定义值。

看来你应该访问一个 props.todo.todo 道具。

<p>{props.todo.todo}</p>

我可能在嵌套级别和 onSnapshot 订阅解包的内容上弄错了,所以它可能只是 props.todo.

<p>{props.todo}</p>

但考虑到在 deleteHandler 中您似乎引用正确 props.todo.id 我确定您需要访问段落中的 props.todo.todo

注意事项

映射数组时,如果您要改变数组(在中间插入、删除元素等),则不要使用数组索引作为 React 键,因为一旦改变数组,键就会移动到不同的元素。使用 doc.id 因为这将是每个元素的内在值。

{todos.map((todo) => (
  <Todo todo={todo} key={todo.id} />
))}

Lists & Keys