当状态更改发生在 ReactJS 中的不同 .js 文件的组件中时,如何更新我的 useEffect 挂钩?

How to update my useEffect hook when State change happen in a different .js file's component in ReactJS?

我正在尝试在 useEffect() 中进行 API 调用,并希望每次在后端添加新数据时调用 useEffect()。 我制作了一个自定义按钮(AddUserButton.js),它在后端添加了一个新用户。我正在尝试显示所有用户的文件 (ManageUsers.js) 中导入此按钮。我只是想制作一个 useState 以在每次单击添加按钮时进行跟踪,并根据它进行 useEffect 刷新。例如:

const [counter, setCounter] = useState(0);
...
const handleAdd = () => {
  setCounter(state => (state+1));
};
...
useEffect(() => {
 // fetch data here
 ...
}, [counter]);
...
return(
 <Button onClick = {handleAdd}> Add User </Button>

);

但目前因为我有两个.js文件,我不确定如何使我的上述逻辑 在这种情况下工作

ManageUsers.js

import AddUserButton from "./AddUserButton";
...
export default function ManageShades() {
...
useEffect(() => {
  axios
  .get("/api/v1/users")
  .then(function (response) {
    // After a successful add, store the returned devices
    setUsers(response.data);
    setGetUserFailed(false);
  })
  .catch(function (error) {
    // After a failed add
    console.log(error);
    setGetUserFailed(true);
  });
console.log("Load User useeffect call")

 },[]);
 return (
<div>
  ...
    <Grid item xs={1}>
      
      <AddUserButton title = "Add User" />
      
    </Grid>
  ...
</div>
);
}

AddUserButton.js

export default function AddDeviceButton() {
...

return (
 <div>
  <Button variant="contained" onClick={handleClickOpen}>
    Add a device
  </Button>
 ...
 </div>
 );
} 

一种常见的方法是将回调函数传递给更新父组件状态的按钮组件。

import { useState, useEffect } from "react";

const AddUserButton = ({ onClick }) => {
  return <button onClick={onClick} />;
};

export default function Test() {
  const [updateCount, setUpdateCount] = useState(false);
  const [count, setCount] = useState(0);

  useEffect(() => {
    setCount(count++);
  }, [updateCount]);

  return (
    <div>
      <AddUserButton
        onClick={() => {
          // do something, e.g. send data to your API
          // finally, trigger update
          setUpdateCount(!updateCount);
        }}
      />
    </div>
  );
}

所以你似乎想让 child 更新它的 parent 状态,一个简单的方法是让 parent 提供 child 回调,调用时会更新 parent 的状态。

const parent = ()=>{
   const [count, setCount] = useState(0);
   const increCallback = ()=>{setCount(count + 1)};

   return (<div> 
      <child callback={increCallback}/>
   </div>);
}

const child = (callback)=>{
   return (<button onClick={callback}/>);
}

如果您告诉 ManageUsers 组件在触发 AddUser 事件后立即从 back-end 获取数据,您几乎肯定不会在响应中看到最新的用户。

为什么? back-end 接收新用户请求需要一些时间,通过适当的安全规则需要更长的时间,a对其进行格式化、清理和放置在数据库中的时间稍长,并且该更新可供 API 提取的时间稍长。

我们能做什么? 如果您管理状态中的用户 - 看起来您是这样做的,基于 setUsers(response.data) - 那么您可以添加新的用户直接添加到状态变量,然后用户将立即出现在 UI 中。然后在后台异步添加新的用户数据到back-end

我们该怎么做?这是一个非常简单的流程,看起来像这样(大致基于您现在拥有的组件结构)

function ManageUsers() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch('https://api.com')
      .then(res => res.json())
      .then(res => setUsers(res));
      .catch(err => console.error(err));
  }, [setUsers]);

  const handleAdd = ({ name, phone, dob }) => {
    const newUser = {
      name,
      phone,
      dob
    };
    setUsers([...users, newUser]);
  };

  return (
    <div>
      <UserList data={users} />
      <AddUser add={handleAdd} />
    </div>
  );
}

// ...

function AddUser({ add }) {
  const [userForm, setUserForm] = useState({ name: "", phone: "", dob: "" });


  return (
    // controlled form fields
    <button onClick={() => add(userForm)}>Submit</button>
  );
}

// ...

function UserList({ data }) {
  return (
    <>
      {data.map(user =>
        <p>{user.name></p>
      }
    </>
  );
}

一旦用户使用“提交”按钮添加新用户,它会将新用户传递给已作为道具传递的“添加”功能。然后将用户附加到 ManageUsers 组件的 users 数组,立即将最新的用户数据填充到 UserList 组件中。如果我们等待新的获取请求通过,这将增加延迟,并且我们刚刚添加的最新用户不太可能返回响应。