我正在尝试处理表单提交,以便在发生数据获取时显示加载组件。我想在将数据加载到我的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));
});
}
};
如果可能的话,我希望能够在不引入任何新依赖项的情况下做到这一点。
使用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;
}
};
我希望对您有所帮助,让我知道它是否适用于您的情况:)
此致敬意