繁体   English   中英

当 State 在 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 文件,所以我不确定在这种情况下如何使我的上述逻辑起作用

管理用户.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>
);
}

添加用户按钮.js

export default function AddDeviceButton() {
...

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

一种常见的方法是将回调 function 传递给更新父组件的 state 的按钮组件。

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>
  );
}

因此,您似乎正在尝试让孩子更新其父母的 state,一种简单的方法是让父母为孩子提供回调,这将在调用时更新父母的 state。

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 事件后立即从后端获取数据,您几乎肯定不会在响应中看到最新的用户。

为什么? 后端接收新用户请求需要一些时间,通过适当的安全规则需要一些时间,格式化、清理和放入数据库需要一些时间,还有一点时间该更新可用于 API 的时间更长。

我们可以做什么? 如果您根据setUsers(response.data)管理 state 中的用户——这看起来像您所做的——那么您可以将新用户直接添加到 state 变量,然后该用户将立即出现在 UI 中。 然后在后台将新的用户数据异步添加到后端。

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

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>
      }
    </>
  );
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM