等待带有 React Hooks 的 Redux Action
Posted
技术标签:
【中文标题】等待带有 React Hooks 的 Redux Action【英文标题】:Awaiting Redux Action w/ React Hooks 【发布时间】:2019-10-23 05:42:24 【问题描述】:我正在尝试处理表单提交以在数据获取发生时显示加载组件。我想在数据加载到我的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);
相关操作(startFetchData
和 setData
)位于另一个文件中,如下所示:
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));
);
;
如果可能的话,我希望能够在不引入任何新依赖项的情况下做到这一点。
【问题讨论】:
从 redux 调度动作修改/更新状态值可能被认为是工作 react-redux 的反模式,您应该考虑将loading
移动到页面的减速器中并简单地从那里调度动作, loading
现在将成为道具
对不起,我不明白这条评论。即使我将 isLoading 作为道具传递给我的 DataTable,也不能解决我的问题。我仍在尝试等待 fetchData redux 操作。
【参考方案1】:
使用 TypeScript 的注意事项:如果你想 await
使用 useDispatch()
的操作返回的承诺,你可能会看到 TypeScript 抱怨不必要的 await
。
在这种情况下,请确保通过泛型将正确的类型(参见 ThunkDispatch)添加到 useDispatch
。
还有useEffect()
和async-await syntax 确保将async
代码包装在另一个闭包中,因为useEffect()
期望void
返回值,否则Typescript 会抱怨您返回Promise。
const dispatch = useDispatch<ThunkDispatch<any, any, Action>>();
useEffect(() =>
(async () =>
const myResult = await dispatch(...);
const anotherResult = await dispatch(...);
// ...
)();
);
【讨论】:
【参考方案2】:我推荐你使用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
给这只鸭子(类型、动作和reducers在同一个文件中,查看更多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;
;
我希望对你有所帮助,如果它对你的情况有用,请告诉我:)
最好的问候
【讨论】:
以上是关于等待带有 React Hooks 的 Redux Action的主要内容,如果未能解决你的问题,请参考以下文章