当状态更改发生在 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 组件中。如果我们等待新的获取请求通过,这将增加延迟,并且我们刚刚添加的最新用户不太可能返回响应。
我正在尝试在 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 组件中。如果我们等待新的获取请求通过,这将增加延迟,并且我们刚刚添加的最新用户不太可能返回响应。