0

我正在尝试重现我使用 Reactjs/Redux/redux-thunk 所做的事情:

  • 显示微调器(在加载期间)
  • 从远程服务器检索信息
  • 显示信息并移除微调器

该方法是使用useReducer模拟本教程中解释的useContextredux 。对于异步部分,我依赖 . ,但我不知道是否有任何替代方法。这是我的代码:redux-thunkuseReducer

组件本身:

  const SearchForm: React.FC<unknown> = () => {
  const { dispatch } = React.useContext(context);
  // Fetch information when clickin on button
  const getAgentsInfo = (event: React.MouseEvent<HTMLElement>) => {
    const fetchData:() => Promise<void> = async () => {
      fetchAgentsInfoBegin(dispatch);           //show the spinner
      const users = await fetchAgentsInfo();    // retrieve info  
      fetchAgentsInfoSuccess(dispatch, users);  // show info and remove spinner
    };
    fetchData();
  }
  return (
   ...
  )

数据提取器文件:

export const fetchAgentsInfo:any = () => {
  const data = await fetch('xxxx');
  return await data.json();
};

动作文件:

export const fetchAgentsInfoBegin = (dispatch:any) => {
  return dispatch({ type: 'FETCH_AGENTS_INFO_BEGIN'});
};

export const fetchAgentsInfoSuccess = (dispatch:any, users:any) => {
  return dispatch({
    type: 'FETCH_AGENTS_INFO_SUCCESS',
    payload: users,
  });
};

export const fetchAgentsInfoFailure = (dispatch:any) => {
  return dispatch({
    type: 'FETCH_AGENTS_INFO_FAILURE'
  })
};

我的商店本身:

import React, { createContext, useReducer } from 'react';
import {
  ContextArgs, 
  ContextState, 
  ContextAction
} from './types';

// Reducer for updating the store based on the 'action.type'
const Reducer = (state: ContextState, action: ContextAction) => {
  switch (action.type) {
    case 'FETCH_AGENTS_INFO_BEGIN':
      return { 
        ...state,
        isLoading:true,
      };
    case 'FETCH_AGENTS_INFO_SUCCESS':
      return { 
        ...state,
        isLoading:false,
        agentsList: action.payload,
      };
    case 'FETCH_AGENTS_INFO_FAILURE':
      return { 
        ...state,
        isLoading:false,
        agentsList: [] };
    default:
      return state;
  }
};

const Context = createContext({} as ContextArgs);

// Initial state for the store
const initialState = {
  agentsList: [],
  selectedAgentId: 0,
  isLoading:false,
};

export const ContextProvider: React.FC = ({ children }) => {
  const [state, dispatch] = useReducer(Reducer, initialState);
  const value = { state, dispatch };
  Context.displayName = 'Context';
  return (
    <Context.Provider value={value}>{children}</Context.Provider>
  );
};

export default Context;

我尝试部分重用本文中的逻辑,但从未显示微调器(数据已正确检索和显示)。

您的帮助将不胜感激!谢谢

4

1 回答 1

2

我在您发布的代码中看不到任何可能导致您描述的问题的内容,也许在减速器中执行 console.log 以查看发生了什么。

我确实有一个建议,通过使用一种 thunk 动作并用常量替换魔术字符串来更改代码并将逻辑移出组件并进入动作:

//action types
const BEGIN = 'BEGIN',
  SUCCESS = 'SUCCESS';
//kind of thunk action (cannot have getState)
const getData = () => (dispatch) => {
  dispatch({ type: BEGIN });
  setTimeout(() => dispatch({ type: SUCCESS }), 2000);
};
const reducer = (state, { type }) => {
  if (type === BEGIN) {
    return { ...state, loading: true };
  }
  if (type === SUCCESS) {
    return { ...state, loading: false };
  }
  return state;
};
const DataContext = React.createContext();
const DataProvider = ({ children }) => {
  const [state, dispatch] = React.useReducer(reducer, {
    loading: false,
  });
  //redux-thunk action would receive getState but
  //  cannot do that because it'll change thunkDispatch
  //  when state changes and could cause problems when
  //  used in effects as a dependency
  const thunkDispatch = React.useCallback(
    (action) =>
      typeof action === 'function'
        ? action(dispatch)
        : action,
    []
  );
  return (
    <DataContext.Provider
      value={{ state, dispatch: thunkDispatch }}
    >
      {children}
    </DataContext.Provider>
  );
};
const App = () => {
  const { state, dispatch } = React.useContext(DataContext);
  return (
    <div>
      <button
        onClick={() => dispatch(getData())}
        disabled={state.loading}
      >
        get data
      </button>
      <pre>{JSON.stringify(state, undefined, 2)}</pre>
    </div>
  );
};
ReactDOM.render(
  <DataProvider>
    <App />
  </DataProvider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>

于 2020-06-28T08:37:58.590 回答