【问题标题】:useReducer + Context api + useEffect = infinite loopuseReducer + Context api + useEffect = 无限循环
【发布时间】:2020-12-01 16:55:06
【问题描述】:

我正在尝试使用 useReducer 和 context api 进行练习,但是在尝试执行返回数据的函数时,我得到了一个无限循环

reducer.js

const initialStore = {
  disabledAddButton: false,
  disabledDelButton: false,
  user: null,
  total_purchase: 0,
  cart: [],
  tasks: [],
}

const reducer = (state, action) => {
  switch (action.type) {
    case TYPES.USER_GET_TASKS: {
      return {
        ...state,
        tasks: action.payload,
      }
    }
    default:
      return state
   }
 }

UserProvider.js

const UserContext = createContext()

const UserProvider = ({ children }) => {
 
  const [store, dispatch] = useReducer(reducer, initialStore)

const getTasks = async () => {
    try {
      const response = await db.collection('tasks').get()
      const arrayData = response.docs.map(doc => ({
        id: doc.id,
        ...doc.data(),
      }))

      dispatch({
        type: TYPES.USER_GET_TASKS,
        payload: arrayData,
      })
    } catch (error) {
      console.log(error)
    }
  }
const value = {
    store,
    getTasks,
    dispatch,
  }
  return <UserContext.Provider value={value}>{children}</UserContext.Provider>
}

export { UserContext }
export default UserProvider

Tasks.js

const Tasks = () => {
  const { store, getTasks } = useContext(UserContext)
  const { tasks } = store
      
  useEffect(() => {
    getTasks()
  }, [])

  return (
    <div>
      {tasks.map(task => (
        <h2 key={task.id}>{task.name}</h2>
      ))}
    </div>
  )
}

export default Tasks

基本上问题是当我在任务组件(useEffect 内部)上运行 getTasks() 时出现无限循环,我不知道为什么

【问题讨论】:

  • 你有没有得到这个答案?我也有同样的问题。

标签: reactjs use-effect use-reducer


【解决方案1】:

这一定与 firebase db 有关,因为我无法通过 API 提取来复制该问题。

您可以使用useMemouseCallback 最小化来自UserProvider 的重新渲染。现在getTasks 函数将只创建一次,而不是在每次渲染时重新创建。

const UserProvider = ({ children }) => {
  const [store, dispatch] = useReducer(reducer, initialStore);

  const getTasks = useCallback(async () => {
    try {
      const response = await db.collection("tasks").get();
      const arrayData = response.docs.map((doc) => ({
        id: doc.id,
        ...doc.data()
      }));
      dispatch({
        type: TYPES.USER_GET_TASKS,
        payload: arrayData
      });
    } catch (error) {
      console.log(error);
    }
  }, [dispatch]);

  const value = useMemo(
    () => ({
      store,
      getTasks,
      dispatch
    }),
    [store, getTasks, dispatch]
  );

  return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};

希望对您有所帮助!

【讨论】:

    猜你喜欢
    • 2020-02-22
    • 1970-01-01
    • 2021-06-12
    • 2021-01-22
    • 2021-01-31
    • 2020-04-14
    • 2021-02-15
    • 2020-09-06
    相关资源
    最近更新 更多