反应useContext useReducer状态挂钩错误

时间:2020-09-21 13:32:09

标签: javascript reactjs react-hooks

import Axios from "axios";
import React, { createContext, useEffect, useReducer, useState } from "react";
import useAsync from "./useAsync";

const [datas, setDatas] = useState(null);

const fatchData = async () => {
  try {
    const response = await Axios.get(
      "https://jsonplaceholder.typicode.com/users"
    );
    setDatas(response.data);
  } catch (e) {
    console.log(e);
  }
};
useEffect(() => {
  fatchData();
  //eslint-disable-next-line
}, deps);
const AppReducer = (state, action) => {
  switch (action.type) {
    default:
      return state;
  }
};
export const GlobalContext = createContext(datas);

export const GlobalProvider = ({ children }) => {
  const [state, dispatch] = useReducer(AppReducer, datas);

  return (
    <GlobalContext.Provider value={{ datas }}>
      {children}
    </GlobalContext.Provider>
  );
};

这是错误。可能由于以下原因之一而发生这种情况。

  1. 您可能错过了React和Render的版本(例如React DOM) 您可能正在违反钩子规则 您可能在同一应用中拥有多个React副本。

我想将接收API的数据作为useReducher的默认值。但是出现了一个钩子错误。 您不能删除或修改使用useContext接收到的数据吗?

如果我使用Graphql而不是restAPI,它将正常工作吗? 有没有一种好方法来管理使用useContext从服务器接收的数据?

1 个答案:

答案 0 :(得分:2)

您需要将每个钩子移到功能组件的主体中。如果从技术上讲它们不在此范围之内,则它们将违反钩子规则。进一步了解Rules of Hooks

请勿在循环,条件或嵌套函数中调用Hook。相反,请始终在React函数的顶层使用Hook。通过遵循此规则,可以确保每次渲染组件时都以相同的顺序调用Hook。这就是让React在多个useStateuseEffect调用之间正确保留Hooks状态的原因。

尝试以下操作:

import Axios from "axios";
import React, { createContext, useEffect, useReducer, useState } from "react";
import useAsync from "./useAsync";

export const GlobalContext = createContext(null);

export const GlobalProvider = ({ children }) => {
  const [state, dispatch] = useReducer(AppReducer, datas);
  const [datas, setDatas] = useState(null);

  const fatchData = async () => {
    try {
      const response = await Axios.get(
        "https://jsonplaceholder.typicode.com/users"
      );
      setDatas(response.data);
    } catch (e) {
      console.log(e);
    }
  };

  useEffect(() => {
    fatchData();
    //eslint-disable-next-line
  }, deps);

  const AppReducer = (state, action) => {
    switch (action.type) {
      default:
        return state;
    }
  };

  return (
    <GlobalContext.Provider value={{ datas }}>
      {children}
    </GlobalContext.Provider>
  );
};