React -在useEffect发生之前等待状态更新



我有一个组件(ItemsIndex),它使用自定义钩子从我们的API中获取数据。但是ItemsIndexuseEffect首先运行,因此DOM还没有被可以滚动到视图中的元素填充。我怎么能等待useItems首先加载,以便DOM呈现itemTree元素和Id,我认为这也会解决滚动问题,因为它会通过Id找到元素。

const ItemsIndex = () => {
const itemsContext = useContext(ItemsContext);
const [uploaditemModalOpen, setUploaditemModalOpen] = useState(false);
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
const [deleteitem, setDeleteitem] = useState("");
const { error, loading, items, itemId, setItems } = useItems();
if (error) {
console.error(error);
}
const resolvedItems = loading ? MOCK_ITEMS : items;
useEffect(() => {
// Decode the itemDownload query parameter from the URL
const params = new URLSearchParams(window.location.search);
const itemDownload = params.get("itemDownload");
if (!itemDownload) return;
const decodedItemPath = decodeURIComponent(itemDownload);
try {
scrollToItem(decodedItemPath); // Doesn't scroll the item into view because can't find the element with id, as its not rendered yet.
} catch (error) {
console.error(error);
}
}, []);

使用Items钩子:

export const useItems = () => {
const [items, setItems] = useState<ItemTree>({ content: {} });
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const { scope, groupData } = useSelector(state);
const itemId = scope.ItemId;
const groupHierarchy = groupData?.path || undefined;
useEffect(() => {
const cachedItems = StorageUtils.get(Items_KEY);
if (cachedItems) {
setItems(JSON.parse(cachedItems));
return;
}
const retrieveVisibleItems = async () => {
try {
setLoading(true);
const { authItems } = await fetchItems(itemId, groupHierarchy);
setItems(authItems);
StorageUtils.set(Items_KEY, JSON.stringify(authItems));
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
retrieveVisibleItems();
}, [itemId, groupHierarchy]);
return { error, loading, items, itemId, setItems };

所有钩子都按照它们被写入的顺序依次执行。因此,useItems应该在ItemsIndex中的useEffect之前被调用。

你的问题是useItems通过从服务器获取数据异步更新items,而当useEffect执行时,items仍然没有被获取。

useEffect中,您需要检查items是否已加载,即创建对items的依赖。

const ItemsIndex = () => {
const { items } = useItems();

useEffect(() => {
if (Object.keys(items?.content) === 0) { // condition that items are not loaded
return;
}
scrollToItem(...);
}, [items]);
// rest code
};

items变量更新时,它将首先渲染DOM,然后调用此useEffect