当子组件设置状态时,父组件不更新数据

问题描述 投票:0回答:1

我有一个表单,它从父组件获取用户数据作为

prop
进行更新,更新它们然后设置父组件的状态,但是当
userData
状态更改时父组件不会重新渲染,因此我必须刷新页面查看更新

父组件


  useEffect(() => {
    const getUsers = async () => {
      const res = await fetch("http://localhost:8000/api/users", {
        credentials: "include",
      });

      const data = await res.json();
      if (data.status === 401) {
        dispatch({ type: "LOGOUT" });
        navigate("/login");
      }
      setUsers(data.users);
      // setUsers(data.users.filter((u) => u.id != 80));
    };
    getUsers();
  }, [dispatch, navigate, user?.id]);

  let emptyUser = {
    id: "",
    firstName: "",
    lastName: "",
    position: "",
    gender: "",
    birthDate: "",
    status: "",
    isAdmin: "",
    image: null,
    url: "",
  };

  const [userData, setUserData] = useState(emptyUser);

  const editUser = (user) => {
    setUserData(user);
  };

子组件

function UpdateUser({ userData, editditUser }) {


  const onSelectFile = (e) => {
    if (!e.target.files || e.target.files.length === 0) {
      editUser({ ...userData, image: undefined });
      return;
    }

    editUser({ ...userData, image: e.target.files[0] });
    setDisableBtn(false);
  };

  const onInputChange = (e, variable) => {
    const val = (e.target && e.target.value) || "";
    let _user = { ...userData };
    _user[`${variable}`] = val;

    editUser(_user);
    setDisableBtn(false);
  };

  const editUser = async (e) => {
    e.preventDefault();
    let errors = {};

    if (
      userData.firstName.length > 15 ||
      userData.lastName.length > 15 ||
      userData.firstName.length < 3 ||
      userData.lastName.length < 3
    ) {
      errors.errName =
        "First name and/or must be between 3 and 15 characters in length.";
    }
    if (!userData.gender) {
      errors.errGender = "Gender must not be empty.";
    }
    if (!userData.status) {
      errors.errStatus = "Status must not be empty.";
    }

    setErrors(errors);

    if (Object.keys(errors).length > 0) {
      return;
    }
    setDisableBtn(true);
    let url;
    if (preview) {
      const imageRef = storageRef(storage, `images/${Date.now()}`);
      const snapshot = await uploadBytes(imageRef, userData.image);
      url = await getDownloadURL(snapshot.ref);
    }

    const userToUpdate = {
      firstName: userData.firstName,
      lastName: userData.lastName,
      email: userData.email,
      position: userData.position,
      gender: userData.gender,
      birthDate: userData.birthDate,
      image: url || userData.image,
      status: userData.status,
      isAdmin: userData.isAdmin === "Admin" ? 1 : 0,
    };
    const res = await fetch(
      `http://localhost:8000/api/edit-user/${userData.id}`,
      {
        credentials: "include",
        method: "PUT",
        body: JSON.stringify(userToUpdate),
        headers: { "Content-Type": "application/json" },
      }
    );
    const data = await res.json();
    if (data.status === 401) {
      dispatch({ type: "LOGOUT" });
      navigate("/login");
    }
    if (data.status === 400) {
      setDisableBtn(false);
      setErrUser(data.message);
      return false;
    }
    console.log("success");
  };
}
reactjs state rerender
1个回答
0
投票

IIUC,父组件获取用户列表(从后端),并保持

userData
状态以在需要时编辑这些用户之一。此
userData
状态与子组件共享,子组件显示编辑表单并处理对后端的请求,以在提交表单时保存更新的用户数据。

但是父级中的列表并不反映该用户的更改,因为显示的数据不是已修改的状态。

在这种情况下,您可以通过多种方式显示更新后的用户,具体取决于您的 Parent JSX 的结构以及它如何调用 Child。

鉴于您共享的代码,解决方案之一可能是在更新请求成功后重新获取整个用户列表。额外的优点是您一定会检索后端实际存储的内容(它可能会清理/拒绝某些更新):

// PARENT
// Build the fetch function separately, so that it can be called imperatively
// once the update request succeeds
const getUsers = useCallback(async () => {
  const res = await fetch("http://localhost:8000/api/users", {
    credentials: "include",
  });

  const data = await res.json();
  if (data.status === 401) {
    dispatch({ type: "LOGOUT" });
    navigate("/login");
  }
  setUsers(data.users);
}, [dispatch, navigate]);

// Fetch users list initially 
useEffect(() => {
  getUsers();
}, []);

return <UpdateUser
  onUpdateSuccess={getUsers} // Pass the fetch function as callback
  // Other props
/>;

// CHILD (UpdateUser)
function UpdateUser({
  onUpdateSuccess,
  // Other props
}) {
  const editUser = async (e) => {
    // Prepare data, send request to Backend...
    console.log("success");
    // Fire the callback
    onUpdateSuccess?.();
  };
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.