在 React useEffect 钩子中设置钩子状态
Setting hook state inside React useEffect hook
我正在尝试为我的一门课程中的 React 作业创建自定义数据获取挂钩。这是一个简单的挂钩,可以访问几个 REST API 端点并创建一个库存对象,该应用程序将其用于 sallad 组合组件。问题是我似乎无法从获取数据的 useEffect
挂钩中设置挂钩的内部状态。我以前多次使用过这种方法,但我完全不知道是什么原因导致了这种行为。无论我在我的 useEffect
函数中尝试使用 setContent
,它总是保持 null
。
请帮忙!
const useInventory = (baseURL) => {
const [loading, setLoading] = useState(false);
const [content, setContent] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
const types = ['foundations', 'extras', 'proteins', 'dressings'];
const urls = types.map(endp => `${baseURL}/${endp}`);
Promise
.all(urls.map(u => fetch(u)))
.then(responses => Promise.all(responses.map(res => res.json())))
.then(data => {
const inventory = data.reduce((acc, curr, i) =>
({ ...acc, [types[i]]: curr }),
{});
// This logs the inventory in desired format
// e.g { foundations: Array, extras: Array, ... }
console.log(inventory);
setContent(inventory);
})
.catch(err => {
setError(err);
})
.finally(() => {
setLoading(false);
// This logs null, for some reason
console.log(content);
});
}, [baseURL]);
return [content, loading, error];
}
设置状态不是同步的,您不会在 finally 块中获得更新的内容。
如果您想调试内容更改的值,您可以像下面那样使用 useEffect 和控制台。
useEffect(() => {
console.log(content);
}, [content])
试试这个就可以了
const useInventory = baseURL => {
const [loading, setLoading] = useState(false);
const [content, setContent] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
const types = ["foundations", "extras", "proteins", "dressings"];
const urls = types.map(endp => `${baseURL}/${endp}`);
function getData() {
Promise.all(urls.map(u => fetch(u)))
.then(responses => Promise.all(responses.map(res => res.json())))
.then(data => {
const inventory = data.reduce(
(acc, curr, i) => ({ ...acc, [types[i]]: curr }),
{}
);
// This logs the inventory in desired format
// e.g { foundations: Array, extras: Array, ... }
console.log(inventory);
setContent(inventory);
})
.catch(err => {
setError(err);
});
}
getData();
}, [baseURL, content]);
console.log(content);
return [content, loading, error];
};
`
我正在尝试为我的一门课程中的 React 作业创建自定义数据获取挂钩。这是一个简单的挂钩,可以访问几个 REST API 端点并创建一个库存对象,该应用程序将其用于 sallad 组合组件。问题是我似乎无法从获取数据的 useEffect
挂钩中设置挂钩的内部状态。我以前多次使用过这种方法,但我完全不知道是什么原因导致了这种行为。无论我在我的 useEffect
函数中尝试使用 setContent
,它总是保持 null
。
请帮忙!
const useInventory = (baseURL) => {
const [loading, setLoading] = useState(false);
const [content, setContent] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
const types = ['foundations', 'extras', 'proteins', 'dressings'];
const urls = types.map(endp => `${baseURL}/${endp}`);
Promise
.all(urls.map(u => fetch(u)))
.then(responses => Promise.all(responses.map(res => res.json())))
.then(data => {
const inventory = data.reduce((acc, curr, i) =>
({ ...acc, [types[i]]: curr }),
{});
// This logs the inventory in desired format
// e.g { foundations: Array, extras: Array, ... }
console.log(inventory);
setContent(inventory);
})
.catch(err => {
setError(err);
})
.finally(() => {
setLoading(false);
// This logs null, for some reason
console.log(content);
});
}, [baseURL]);
return [content, loading, error];
}
设置状态不是同步的,您不会在 finally 块中获得更新的内容。
如果您想调试内容更改的值,您可以像下面那样使用 useEffect 和控制台。
useEffect(() => {
console.log(content);
}, [content])
试试这个就可以了
const useInventory = baseURL => {
const [loading, setLoading] = useState(false);
const [content, setContent] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
const types = ["foundations", "extras", "proteins", "dressings"];
const urls = types.map(endp => `${baseURL}/${endp}`);
function getData() {
Promise.all(urls.map(u => fetch(u)))
.then(responses => Promise.all(responses.map(res => res.json())))
.then(data => {
const inventory = data.reduce(
(acc, curr, i) => ({ ...acc, [types[i]]: curr }),
{}
);
// This logs the inventory in desired format
// e.g { foundations: Array, extras: Array, ... }
console.log(inventory);
setContent(inventory);
})
.catch(err => {
setError(err);
});
}
getData();
}, [baseURL, content]);
console.log(content);
return [content, loading, error];
};
`