Reputation: 227
I'm trying to dispatch a tryAutoLogin function. That tryAutoLogin function checks is AsyncStorage if there is data, and updates the auth state using the setCredentials action. I'm calling the function like this:
const autoLoginAndInitialize = async () => {
dispatch(tryAutoLogin());
updateDeviceId();
};
and the tryAutoLogin function looks like this:
export const tryAutoLogin = () => async (dispatch: AppDispatch) => {
try {
const userData = await AsyncStorage.getItem("userData");
if (userData) {
const parsedUserData = JSON.parse(userData);
console.log("parsed data", parsedUserData);
dispatch(auth.actions.setCredentials({ ...parsedUserData }));
}
} catch (err) {
console.error("Error while trying to auto-login:", err);
}
};
However, I'm getting a red underline in the tryAutoLogin()
after the dispatch, with the following error:
Argument of type '(dispatch: AppDispatch) => Promise<void>' is not assignable to parameter of type 'AnyAction'.
I tried changing the dispatch type to several different types but I haven't been successful. This structure was working OK in plain JS, but when changing to TS is giving this error. Any clue of what's wrong?
Edit:
My store.ts configuration looks like this:
const store = configureStore({
reducer: persistedReducer,
middleware: [thunk],
devTools: true,
});
export const persistor = persistStore(store);
export type AppDispatch = typeof store.dispatch;
export default store;
As mentioned in the documentation, I'm using a custom useDispatch and useSelector in a separate hooks file:
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import { RootState } from "../redux/rootReducer";
import { AppDispatch } from "../redux/store";
type DispatchFunc = () => AppDispatch;
export const useAppDispatch: DispatchFunc = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
Then, the complete snippet of where I'm calling the tryAutoLogin() function is this one:
const AppNavigator = (): React.ReactElement => {
const dispatch = useAppDispatch();
const permissionStatus = useAppSelector(
notificationSelectors.selectPermissionStatus
);
const expoPushToken = useAppSelector(notificationSelectors.selectExpoPushToken);
useEffect(() => {
const updateDeviceId = async () => {
await saveDeviceCredentials();
initializeApp(dispatch, permissionStatus, expoPushToken);
};
const autoLoginAndInitialize = async () => {
dispatch(tryAutoLogin());
updateDeviceId();
};
autoLoginAndInitialize();
Again, the error regarding the dispatch(tryAutoLogin());
is the following:
Argument of type '(dispatch: AppDispatch) => Promise<void>' is not assignable to parameter of type 'AnyAction'.ts(2345)
(alias) tryAutoLogin(): (dispatch: any) => Promise<void>
import tryAutoLogin
Edit 2:
Using createAsyncThunk
in the tryAutoLogin() function instead leads to this new error:
Argument of type 'AsyncThunkAction<void, void, AsyncThunkConfig>' is not assignable to parameter of type 'AnyAction'.
having trouble using dispatch() in other parts of my app, considering the problem to be exclusively from dispatch?
this is the tryAutoLogin function with createAsyncThunk:
export const tryAutoLogin = createAsyncThunk(
"auth/tryAutoLogin",
async (_, { dispatch }) => {
try {
const userData = await AsyncStorage.getItem("userData");
if (userData) {
const parsedUserData = JSON.parse(userData);
console.log("parsed data", parsedUserData);
dispatch(auth.actions.setCredentials({ ...parsedUserData }));
}
} catch (err) {
console.error("Error while trying to auto-login:", err);
throw err;
}
}
);
Upvotes: 0
Views: 149
Reputation: 51
Dispatch has a 'generic' type that determines the type of dispatch. As you haven't provided any type to the dispatch it is in AnyAction
type. Simply type the dispatch like so and you're good to go!:
const dispatch = useDispatch<AppDispatch>()
const autoLoginAndInitialize = async () => {
dispatch(tryAutoLogin())
updateDeviceId()
}
Upvotes: 0