等待带有React Hooks的Redux动作

时间:2019-06-07 17:40:30

标签: javascript reactjs redux redux-thunk react-hooks

我正在尝试处理表单提交,以在发生数据提取时显示加载组件。我想在将数据加载到我的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));
        });
    }
};

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

2 个答案:

答案 0 :(得分:0)

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

Store.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

给这只鸭子(类型,动作和归约器放在同一个文件中,请查看更多here

// ----------------------------------------------------------------
// 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;
  }
};

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

最诚挚的问候

答案 1 :(得分:0)

使用TypeScript的用户的注释:如果您想await使用useDispatch()的操作返回的承诺,您可能会看到TypeScript抱怨不必要的{{1} }。

在这种情况下,请确保通过泛型向await添加正确的类型(请参见ThunkDispatch)。

还要将useDispatchasync-await syntax一起使用,并确保将useEffect()代码包装在另一个闭包中,因为async期望返回值useEffect(),而Typescript会抱怨您返回一个承诺。

void