等待带有反应钩子的 Redux 操作



我正在尝试处理表单提交,以便在发生数据获取时显示加载组件。我想在将数据加载到我的Redux存储时显示数据。

现在,我已经将我的组件设置为使用React钩子。虽然数据成功加载到我的redux存储中,但我不确定如何"等待"操作完成的结果。以下是我的组件外观的简化版本:

const DataPage = (props) => {
    const [isLoading, setIsLoading] = useState(false);
    const [isError, setError] = useState(false);
    useEffect(() => { // Reset Filters when dataSource changes...
        setError(false);
        setIsLoading(false);
    }, [dataSource]);
    const handleSubmit = (e, { dataSource }) => {
        e.preventDefault();
        setError(false)
        setIsLoading(true);
         //// IDEALLY THIS IS WHERE THE FIX WOULD GO? TURN THIS INTO ASYNC/AWAIT?
        props.fetchData({ dataSource, token: localStorage.JWT_TOKEN });
    };
    return (    
        <div className="dataPage">
            <form className="dataPage__filters" onSubmit={(e) => handleSubmit(e, { dataSource })}>
                <DataSelector dataSource={dataSource} setDataSource={setDataSource}/>
                <button className="button">
                   Search
                </button>
            </form>
            {isError && <div>Something went wrong...</div>}
            { isLoading ? ( <div>...Loading </div> ) : (
                <div className="dataPage__table">
                    <DataTable /> // This is connected to my redux-store separately through 'connect'
                </div>
            )}
        </div>
    );
};
const mapDispatchToProps = (dispatch) => ({
    fetchData: ({ dataSource, token }) => dispatch(startFetchData({ dataSource, token }))
});
export default connect(null, mapDispatchToProps)(DataPage);

相关操作(startFetchDatasetData (位于另一个文件中,如下所示:

export const setData = (data) => ({
    type: "SET_DATA",
    data
});
export const startFetchData = ({ dataSource, filter, filterTarget, token }) => {
    return (dispatch) => {
        axios.get(`${'http://localhost:8081'}/api/${dataSource}`, { headers: { authorization: token }})
        .then((res) => {
            dispatch(setData(result));
        });
    }
};

如果可能的话,我希望能够在不引入任何新依赖项的情况下做到这一点。

使用TypeScript的人的注意事项:如果你想await使用useDispatch()的操作返回的承诺,你可能会看到TypeScript抱怨不必要的await

在这种情况下,请确保通过泛型添加正确的类型(请参阅 ThunkDispatch(以useDispatch

同样,使用 async-await 语法的 useEffect(),请确保将async代码包装在另一个闭包中,因为useEffect()期望返回void值,而 Typescript 会抱怨您返回 Promise。

const dispatch = useDispatch<ThunkDispatch<any, any, Action>>();
useEffect(() => {
  (async () => {
    const myResult = await dispatch(...);
    const anotherResult = await dispatch(...);
    // ...
  })();
});

我建议你使用redux-thunk中间件。这是一个非常简单且有用的库,可以将您的操作变成函数(包括异步函数(而不是对象。我给你举个例子:

商店.js

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
import api from './services/api';
// Note: this API requires redux@>=3.1.0
const store = createStore(
  rootReducer,
  // With extra argument, in this case, my API):
  applyMiddleware(thunk.withExtraArgument(api));
);


AuthDuck.js

给这只鸭子(类型,动作和化简器在同一文件中,在此处查看更多(

// ----------------------------------------------------------------
// Types
// ----------------------------------------------------------------
const Types = {
  SIGN_IN_START: 'SIGN_IN_START',
  SIGN_IN_SUCCESS: 'SIGN_IN_SUCCESS',
  SIGN_IN_FAIL: 'SIGN_IN_FAIL'
};
// ----------------------------------------------------------------
// Actions
// ----------------------------------------------------------------
const signin = function (user) {
  // LOOK HERE!
  // Redux Thunk able you to return a function instead of an object.
  return async function (dispatch, getState, api) {
    try {
      dispatch({ type: Types.SIGN_IN_START });
      const token = await api.access.signin(user);
      dispatch({ type: Types.SIGN_IN_SUCCESS, payload: token });
    } catch (error) {
      dispatch({ type: Types.SIGN_IN_FAIL, payload: error });
    }
  };
};
export const Actions = { signin };
// ----------------------------------------------------------------
// Reducers
// ----------------------------------------------------------------
export default function reducer(state, action) {
  switch (action.type) {
    case VeasyCalendarTypes.SIGN_IN_START:
      return { ...state, isLoading: true };
    case VeasyCalendarTypes.SIGN_IN_SUCCESS:
      return { ...state, isLoading: false, token: action.payload };
    case VeasyCalendarTypes.SIGN_IN_FAIL:
      return { ...state, isLoading: false, error: action.payload };
    default:
      return state;
  }
};

我希望对您有所帮助,让我知道它是否适用于您的情况:)

此致敬意

相关内容

  • 没有找到相关文章