我需要以两种不同的方式获取我的数据,并根据此数据进行渲染。在第一次加载时,我需要一个个地获取所有项目并增加计数。之后,我需要立即获取所有数据并更新显示。所以,我写了这样的东西(不是实际的代码,而是几乎相同的东西):
import React, { useEffect } from "react";
import axios from "axios";
import { useGlobalState } from "./state";
const arr = Array.from(Array(100), (x, i) => i + 1);
function App() {
const [{ posts }, dispatch] = useGlobalState();
useEffect(() => {
const getInc = () => {
arr.forEach(async id => {
const res = await axios(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
dispatch({
type: "INC",
payload: res.data
});
});
};
const getAll = async () => {
const promises = arr.map(id =>
axios(`https://jsonplaceholder.typicode.com/posts/${id}`)
);
const res = await Promise.all(promises);
dispatch({
type: "ALL",
payload: res.map(el => el.data)
});
};
if (!posts.length) {
getInc();
} else {
getAll();
}
}, [dispatch]);
return (
<>
<div>{posts.length}</div>
</>
);
}
export default App;
我只是使用Context
和useReducer
创建一个简单的商店。上面的代码按原样工作,但是我跳过添加posts.length
依赖关系,这使我认为我的逻辑是错误的。
我试图使用ref来跟踪初始化状态,但是我需要在每次路由更改时跟踪数据。然后,我尝试通过在商店中添加一个init
状态来保持它的状态,但是我无法使其正常工作。例如,我找不到合适的位置来派发init
。如果我在一次提取后尝试使用它,则会立即触发初始化,并调用其他函数(getAll
)。
如果有人想使用它,这里是一个有效的沙箱:https://codesandbox.io/s/great-monad-402lb
答案 0 :(得分:1)
我已将init
添加到您的商店:
// @dataReducer.js
export const initialDataState = {
init: true,
posts: []
};
const dataReducer = (state, action) => {
switch (action.type) {
case 'ALL':
// init false
return { ...state, posts: action.payload };
case 'INC':
return { ...state, init: false, posts: [...state.posts, action.payload] };
...
}
// @App.js
function App() {
const [{ init, posts }, dispatch] = useGlobalState();
useEffect(() => {
init ? getInc(dispatch) : getAll(dispatch);
}, [init, dispatch]);
...
}