英文:
How to call same API multiple time with different JSON data
问题
我正在编写一个简单的 React 页面,可以从一个 API 获取用户详细信息,并对其进行一些修改后传递到另一个 API 多次。
export default function User() {
const [userid, setUserId] = useState("");
const [userData, setUserData] = useState({});
const synchToLocation = (loc) => {
setUserData((userData) => ({ ...userData, id: 1234, location: loc }));
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
};
fetch("http://localhost:8080/api/v1/synch", requestOptions);
};
const handleSynch = () => {
synchToLocation(1);
synchToLocation(2);
synchToLocation(3);
};
const fetchUser = (event) => {
event.preventDefault();
console.log(userid);
fetch("http://localhost:8080/api/v1/synch/emp?id=" + userid).then((result) =>
result.json().then((e) => {
setUserData({
...userData,
id: e.id,
firstName: e.firstName,
lastName: e.lastName,
role: e.role,
location: e.location,
status: e.status
});
})
);
};
return (
<Container>
<TextField
id="id"
label="user id"
value={userid}
onChange={(e) => setUserId(e.target.value)}
fullWidth
required
></TextField>
<Button
variant="contained"
color="secondary"
type="submit"
onClick={fetchUser}
>
Search
<SearchOutlined />
</Button>
<Box>
<Button variant="contained" color="secondary" onClick={handleSynch}>
Synch
</Button>
</Box>
</Container>
);
}
期望:
- 如果用户点击“Search”按钮,根据用户输入的 ID 获取用户数据并设置到状态中。
- 如果用户点击“Synch”按钮,用户数据应更新为特定的位置,并调用更新后的位置的 API。
实际结果:
- 用户数据在搜索时按预期获取。
- 有时 API 使用旧数据进行调用,或者有时使用最后更新的数据进行调用。
请给我建议如何更好地实现这一点。
英文:
I am writing a simple react page where user details can be fetched from one API and pass it to another API multiple times with some modification.
export default function User() {
const [userid, setUserId] = useState("");
const [userData, setUserData] = useState({});
const synchToLocation=(loc)=>{
setUserData((userData)=>({...userData,id:1234,location:loc}));
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
};
fetch("http://localhost:8080/api/v1/synch" , requestOptions);
}
const handleSynch = () => {
synchToLocation(1);
synchToLocation(2);
synchToLocation(3);
};
const fecthUser = (event) => {
event.preventDefault();
console.log(userid);
fetch("http://localhost:8080/api/v1/synch/emp?id=" + userid).then((result) =>
result.json().then((e) => { setUserData({...userData,id:e.id,firstName:e.firstName,lastName:e.lastName,role:e.role,location:e.location,status:e.status});
})
);
};
return (
<Container>
<TextField
id="id"
label="user id"
value={userid}
onChange={(e) => setUserId(e.target.value)}
fullWidth
required
></TextField>
<Button
variant="contained"
color="secondary"
type="submit"
onClick={fecthUser}
>
Search
<SearchOutlined />
</Button>
<Box>
<Button variant="contained" color="secondary" onClick={handleSynch}>
Synch
</Button>
</Box>
</Container>
);
}
I have one text field and two button (search and synch).
Expectation:
- if user click search button, fetch userdata for user input id and set to state.
- if user click Synch button, user data should update with specific location and call api with updated location.
Actual Result:
- User data fetch on search as expected.
- Api calling with old data or some time calling with last updated data.
Please suggest me the better way to achieve this.
答案1
得分: 0
问题出在这里。因为setState是异步工作的,所以在setUserData之后,请求主体有时会使用旧的userData而不是您之前设置的新userData。
const synchToLocation = (loc) => {
setUserData((userData) => ({ ...userData, id: 1234, location: loc }));
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
};
fetch("http://localhost:8080/api/v1/synch", requestOptions);
}
您应该将对象的body属性更改为
body: JSON.stringify({ ...userData, id: 1234, location: loc })
英文:
The problem is here. Because the setState work asynchronously so after setUserData, the request body sometimes use the old userData over the new userData that u have set earlier.
const synchToLocation=(loc)=>{
setUserData((userData)=>({...userData,id:1234,location:loc}));
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
};
fetch("http://localhost:8080/api/v1/synch" , requestOptions);
}
you should change the property body of object to
body:JSON.stringify({...userData,id:1234,location:loc})
答案2
得分: -1
Hooks 和 useEffect() 将允许您根据更新后的状态来更新本地状态并重新渲染。
参见:https://reactjs.org/docs/hooks-effect.html
const SimpleComp = (userName, fetchUserAPI, fetchLocalParams) => {
const [userData, setUserData] = useState(null);
const [localParams, setLocalParams] = useState(null);
useEffect(() => {
setUserData(fetchUserAPI(userName));
}, []);
useEffect(() => {
setLocalParams(fetchLocalParams(userData));
}, [userData]);
return (
<>UserData: {userData} localParams: {localParams}</>
);
};
export default SimpleComp;
这两个 Hook 的初始状态均为 null。第一个 useEffect() 使用空的监视参数([])将在加载时被调用。第二个 useEffect() 监视 Hook:userData。当 userData 发生变化时,此 useEffect 将被调用,并使用更新后的状态。第一个 useEffect 在加载时调用 fetchUserData,这会将 userData 更新为 API 调用的返回值。这会使用新值设置 User Data。随后,第二个 useEffect 会被调用,因为 userData-Hook 已更改状态。该 useEffect 调用 fetchLocalParametersAPI,并将该 Hook 的值设置为返回的数据。
在所有 useEffects() 被评估后,Hook 状态的所有更改将触发重新渲染。此时,所有 Hook 变量应该是最新的,并根据 userData 渲染 localParameters。
如果您需要使用同步按钮方法,请创建一个 onClick,该 onClick 从文本输入中设置一个新的 userName Hook,并在 onClick() 中更新 userName。只需创建另一个 useEffect,监视 userName,并使用新的用户名调用 fetchUserDataAPI。这将更新 userData Hook,然后在 userData 发生变化时调用 fetchLocalParams。
英文:
Hooks and useEffect() will allow you to update local state and re-render based on this updated state.
see: https://reactjs.org/docs/hooks-effect.html
const SimpleComp = (userName, fetchUserAPI, fetchLocalParams) => {
const [userData, setUserData] = useState(null);
const [localParams, setLocalParams] = useState(null);
useEffect(() => {
setUserData( fetchUserAPI(userName) );
}, []);
useEffect(() => {
setLocalParams( fetchLocalParams(userData) );
}, [userData]);
return (
<>UserData: {userData} localParams: {localParams}</>
);
};
export default SimpleComp;
The initial-state for both Hooks is null. The first useEffect() with empty watch parameters ([]) will be called on-load. The second useEffect() is watching the Hook: userData. When userData changes; this useEffect will be called with the updated state. The first calls the fetchUserData on-load. This updates userData to the return from the API call. This sets User Data with the new value. The second useEffect will then be called because the userData-Hook has changed state. That useEffect calls the fetchLocalParametersAPI and sets this Hook's value to the returned data.
All of these changes in Hook state triggers re-render after all of the useEffects() have been evaluated. At that time; all of the Hook variables should be up-to-date and rendering the localParameters based on the userData.
If you need to use the sync button approach; then create an onClick that sets a new userName Hook from a text-input and update userName onClick(). Just create another useEffect that watches userName and calls fetchUserDataAPI with the new username. This will update the userData Hook which will then call fetchLocalParams when userData changes.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论