首页 > 解决方案 > 如何将从 useEffect 中获取的 initialValue 放在 textField 中?

问题描述

我有这个编辑页面,其中名字、姓氏和地址的初始值应该来自使用 useEffect 从 firebase firestore 检索到的数据。

 useEffect(() => {
    const unsubscribe = firestore
      .collection("users")
      .doc(uid)
      .onSnapshot((snapshot) => {
        const arr = [];
        arr.push({
          ...snapshot.data(),
        });

        setUsers(arr);
      });

    return () => {
      unsubscribe();
    };
  }, []);

handleSubmit 将更新的信息保存在 firestore 中:

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      const userRef = firestore.collection("users").doc(uid);
      const ref = userRef.set(
        {
          firstName,
          middleName,
          lastName,
          address,
        },
        { merge: true }
      );
      console.log(" saved");
    } catch (err) {
      console.log(err);
    }
  };

下面是整个代码:

const edit = () => {
  const uid = location.state;
  const [isLoading, setIsLoading] = useState(false);
  const [users, setUsers] = useState([]);
  const [firstName, setFirstName] = useState("");

  useEffect(() => {
    const unsubscribe = firestore
      .collection("users")
      .doc(uid)
      .onSnapshot((snapshot) => {
        const arr = [];
        arr.push({
          ...snapshot.data(),
        });

        setUsers(arr);
        setIsLoading(true);
      });

    return () => {
      unsubscribe();
    };
  }, []);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(firstName);
  };

  return (
    <div>
        {isLoading ? (
          <>
            {users &&
              users.map((user) => (
                <li style={{ listStyle: "none" }}>
                  <CardHeader title="Update Profile" />
                  <form onSubmit={handleSubmit}>
                    <TextField
                      type="text"
                      value={user.firstName}
                      variant="outlined"
                      label="First Name"
                      fullWidth
                      onChange={(e) => setFirstName(e.target.value)}
                    />
                    <Button type="submit"> Submit</Button>
                  </form>
                </li>
              ))}
          </>
        ) : (
          <h1>Loading...</h1>
        )}
    </div>
  );
};

export default edit;

假设我想编辑用户“John Park”的地址。这些文本字段应该具有 John 的名字和姓氏的初始值,因此即使地址字段是唯一更新的字段,当保存在 firestore 中时,名字和姓氏字段也不会是空字符串。我该怎么做?谢谢你。

标签: javascriptreactjsfirebasegoogle-cloud-firestorematerial-ui

解决方案


似乎您正在更新本地状态,但它没有初始化为空字符串。

您的更新应该是users您获取的本地副本,并且提交处理程序应该获取特定用户以在您的后端进行更新。

const [users, setUsers] = React.useState([]);

更改处理程序 - 柯里化函数以获取索引并返回处理程序。它将前一个状态映射users到下一个状态,更新指定索引处的用户。

const changeHandler = index => e => {
  const { name, value } = e.target;
  setUsers(users => users.map((user, i) => i === index
    ? {
      ...user,
      [name]: value,
    }
    : user,
  ));
};

提交处理程序 - curried 函数以获取特定用户对象的索引以发送到后端。

const handleSubmit = index => async (e) => {
  e.preventDefault();

  try {
    const userRef = firestore.collection("users").doc(uid);
    const ref = userRef.set(
      { ...users[index] }, // <-- user by index
      { merge: true }
    );
    console.log(" saved");
  } catch (err) {
    console.log(err);
  }
};

将当前映射的索引传递给处理程序。将属性添加name到与输入的用户属性名称匹配的每个字段。

return (
  <div>
    {isLoading ? (
      <>
        {users &&
          users.map((user, index) => (
            <li style={{ listStyle: "none" }}>
              <CardHeader title="Update Profile" />
              <form onSubmit={handleSubmit(index)}> // <-- pass index
                <TextField
                  type="text"
                  value={user.firstName}
                  variant="outlined"
                  label="First Name"
                  name="firstName" // <-- add name attribute
                  fullWidth
                  onChange={changeHandler(index)} // <-- pass index to handler
                />
                ... other fields
                <Button type="submit">Submit</Button>
              </form>
            </li>
          ))}
      </>
    ) : (
      <h1>Loading...</h1>
    )}
  </div>
);

推荐阅读