在相同的用途中依赖地使用相同的数据

时间:2019-06-03 09:48:32

标签: javascript reactjs

我需要以两种不同的方式获取我的数据,并根据此数据进行渲染。在第一次加载时,我需要一个个地获取所有项目并增加计数。之后,我需要立即获取所有数据并更新显示。所以,我写了这样的东西(不是实际的代码,而是几乎相同的东西):

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;

我只是使用ContextuseReducer创建一个简单的商店。上面的代码按原样工作,但是我跳过添加posts.length依赖关系,这使我认为我的逻辑是错误的。

我试图使用ref来跟踪初始化状态,但是我需要在每次路由更改时跟踪数据。然后,我尝试通过在商店中添加一个init状态来保持它的状态,但是我无法使其正常工作。例如,我找不到合适的位置来派发init。如果我在一次提取后尝试使用它,则会立即触发初始化,并调用其他函数(getAll)。

如果有人想使用它,这里是一个有效的沙箱:https://codesandbox.io/s/great-monad-402lb

1 个答案:

答案 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]);
...
}

Edit funny-violet-pwew6