我在React中有一个组件,在useEffect
中,我进行了两个API调用并设置了两个状态。仍然停留在useEffect
之后,我试图用API更新的状态之一设置另一个状态。如果通过将useEffect
的方括号参数保持为空来执行此操作,则不会设置状态。如果我在括号中传递状态常量,则会陷入无限循环。
async function fetchData() {
const agentRes = await fetch("http://localhost:3004/agentsdata");
agentRes
.json()
.then(res => setAgents(res))
.catch(err => console.log(err));
const queueRes = await fetch("http://localhost:3004/queuedata");
queueRes
.json()
.then(res => setBaseQueues(res))
.catch(err => console.log(err));
}
useEffect(() => {
fetchData();
let pge;
if (props.location.data !== undefined) {
pge = props.location.data.page;
}
else {pge = 1;}
setUser(props.match.params.user);
setPage(pge);
let lowerB = (0 +((pge - 1) * 10));
let upperB = 10 + ((pge - 1) * 10);
setQueues(baseQueues.slice(lowerB, upperB)); // here the state is not getting set.
}, [queues])
如何做到这一点,以便可以根据需要在useEffect
中进行设置。
答案 0 :(得分:2)
useEffect(() => {
const doAsyncStuff = async () => {
await fetchData(); // wait for this data to load
const { data } = props.location;
let pge = data !== undefined ? data.page : 1;
setUser(props.match.params.user);
setPage(pge);
let lowerB = (0 +((pge - 1) * 10));
let upperB = 10 + ((pge - 1) * 10);
setQueues(state => state.slice(lowerB, upperB)); // change here
}
doAsyncStuff();
}, [queues])
首先,我认为您需要等待数据加载,因此必须等待await fetchData();
然后在设置setQueues
时必须执行setQueues(state => state.slice(lowerB, upperB));
答案 1 :(得分:0)
您可以使用更简单的化学方法:
useEffect(() => {
fetchData();
}, [queues])
useEffect(() => {
let pge;
if (props.location.data !== undefined) {
pge = props.location.data.page;
}
else {pge = 1;}
setUser(props.match.params.user);
setPage(pge);
let lowerB = (0 +((pge - 1) * 10));
let upperB = 10 + ((pge - 1) * 10);
setQueues(baseQueues.slice(lowerB, upperB)); // here baseQueues is updated.
}, [baseQueues])
... ,但您可能不需要其中的大部分
queues
是派生数据; 答案 2 :(得分:0)
我已尝试修复代码,并在注释中给出了有关如何正确使用useEffect钩子的详细说明。我强烈建议您阅读Dan Abramov的this blog post,它将清除您对使用useEffect
钩子的大部分误解
//since you data fetching code does not depend on anything inside your component you can hoist it outside the component.
async function getAgentData(){
try{
const response = await fetch('http://localhost:3004/agentsdata');
return await response.json();
} catch(error){
console.log(error)
}
}
async function getQueueData{
try{
const response = await fetch('http://localhost:3004/queuedata');
return await response.json();
} catch(error){
console.log(error)
}
}
function YourComponent(props){
// destructure your props
const { location: { data }, match } = props;
const { params: { user } } = props.match;
// Split your hooks by concern keep the related code together
useEffect(() => {
setUser(user);
// add ALL you dependencies for this effect
}, [user])
// Second Effect
useEffect(() => {
const pge = (data == undefined)? 1 : data.page;
const lowerB = (0 +((pge - 1) * 10));
const upperB = 10 + ((pge - 1) * 10);
setPage(pge);
async function fetchData(){
const agentRes = await getAgentData();
setAgents(agentRes);
const queueRes = await getQueueData();
// Note: There need to first save it to state; then retrieve then slice then update again. When all you need is this
setBaseQueues(queueRes.slice(lowerB, upperB));
}
//call the function here
fetchData();
//Add the ALL the dependencies of this effect i.e all props, functions, state variables inside
//YourComponent that you have used in this effect
//In this case this effect is only run when this.props.location.data is changes, which is the desired behaviour
}, [ data ])
return <>Whatever</>
}