我正在尝试处理表单提交,以在发生数据提取时显示加载组件。我想在将数据加载到我的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));
});
}
};
我希望能够在不引入任何新依赖的情况下做到这一点。
答案 0 :(得分:0)
我建议您使用redux-thunk中间件。这是一个非常简单实用的库,可以使您的操作(而不是对象)成为函数(包括异步函数)。我给你举个例子:
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));
);
给这只鸭子(类型,动作和归约器放在同一个文件中,请查看更多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)。
还要将useDispatch
与async-await syntax一起使用,并确保将useEffect()
代码包装在另一个闭包中,因为async
期望返回值useEffect()
,而Typescript会抱怨您返回一个承诺。
void