【问题标题】:How to return state in reducer function during API callAPI调用期间如何在reducer函数中返回状态
【发布时间】:2022-01-10 12:48:52
【问题描述】:

我有一个 reducer 函数,我必须在其中进行 API 调用,然后将其结果作为状态返回。但由于 API 调用是异步的,因此 state 的值不会更新。

if (action.type==='CREATE_POST') {
        const x= async () => {
            const res=await  fetch("http://localhost:5000/posts", {
                  method: "post",
                  headers: {
                      'Accept': 'application/json',
                      'Content-Type': 'application/json'
                  },
                  body: JSON.stringify(
                      action.payload
                  )
              })
                  const data= await res.json()
              return data
          }
          return [...state,x]
}

我也试过了

if (action.type==='CREATE_POST') {
        const x= async () => {
            const res=await  fetch("http://localhost:5000/posts", {
                  method: "post",
                  headers: {
                      'Accept': 'application/json',
                      'Content-Type': 'application/json'
                  },
                  body: JSON.stringify(
                      action.payload
                  )
              })
                  const data= await res.json()
              return data
          }
          return [...state,x().then((data)=>{console.log(data);})]

    }

【问题讨论】:

  • 你的 redux reducer 代码在哪里?

标签: javascript reactjs asynchronous async-await fetch


【解决方案1】:

如果您正在执行异步任务,我建议您使用这种模式:

创建3个文件,命名为:

  1. reducer.js
  2. action.js
  3. effect.js(用于异步任务)

在减速器中

const initialState = {
  loading: false,
  data: [],
  error: ''
}

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "FETCH_REQUEST":
      return {
        ...state,
        loading: true
      }
    case "FETCH_SUCCESS":
      return {
        loading: false,
        data: action.payload,
        error: ''
      }
    case "FETCH_FAILURE":
      return {
        loading: false,
        data: [],
        error: action.payload
      }
    default: return state
  }
}

export default reducer

在 action.js 中

export const fetchRequest = () => {
    return {
      type: "FETCH_REQUEST"
    }
  }
  
  export const fetchSuccess = data => {
    return {
      type: "FETCH_SUCCESS",
      payload: data
    }
  }
  
  export const fetchFailure = error => {
    return {
      type: "FETCH_FAILURE",
      payload: error
    }
  }

最后是 effect.js

export const fetch = () => {
    return (dispatch) => {
        //Initializing the request
        dispatch(fetchRequest());
        //Calling the api
        api()
            .then((response) => {
                // response is the data
                dispatch(fetchSuccess(response));
            })
            .catch((error) => {
                // error.message is the error message
                dispatch(fetchFailure(error.message));
            });
    };
};

【讨论】:

    【解决方案2】:

    不要从 reducer 调用 API,reducer 是纯函数,它不会等待 API 调用完成并更新状态。

    创建另一个与组件分离的函数/钩子并在那里执行所有这些操作的最佳方法,这样您的组件就会干净。

    我使用以下方法来解决这个问题,我为每个服务(如 useUserDispach、useAuthDispatch 等)创建了一个自定义挂钩,以使所有这些逻辑远离组件。

    您可以根据您的用例为每个页面/模块/服务等创建自定义调度程序。

    自定义挂钩

     const usePostDispatch = () => {
      const dispatch = useDispatch();
      const getPosts = async () => {
        try {
          dispatch({ type: "FETCH_REQUEST" });
          const res = await fetch("http://localhost:5000/posts", {
            method: "post",
            headers: {
              Accept: "application/json",
              "Content-Type": "application/json",
            },
            body: JSON.stringify(action.payload),
          });
          const data = await res.json();
          dispatch({ type: "FETCH_SUCCESS", payload: data });
          return data;
        } catch (error) {
          dispatch({ type: "FETCH_FAILURE", payload: error });
        }
      };
      return {
        getPosts,
      };
    };
    

    减速器

    const initialState = {
      loading: false,
      data: [],
      error: "",
    };
    
    const reducer = (state = initialState, action) => {
      switch (action.type) {
        case "FETCH_REQUEST":
          return {
            ...state,
            loading: true,
          };
        case "FETCH_SUCCESS":
          return {
            loading: false,
            data: action.payload,
            error: "",
          };
        case "FETCH_FAILURE":
          return {
            loading: false,
            data: [],
            error: action.payload,
          };
        default:
          return state;
      }
    };
    
    export default reducer;
    

    组件

    const { getPosts } = usePostDispatch(); // Make sure you call this at top level
    useEffect(() => {
      getPosts();
    }, []);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-25
      • 2023-02-26
      • 2017-03-26
      • 2020-11-10
      • 2021-10-09
      相关资源
      最近更新 更多