-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeScript createAsyncThunk optional or no args #489
Comments
Yeah, that's not possible at the moment. const _usersLoad = createAsyncThunk(
'users/load',
(filters: UserFilters) => Api.get<User[]>('/api/users/search', filters)
);
export const usersLoad = (filters: UserFilters = {}) => _usersLoad(filters); I admit it's a bit hacky, but it should do as a workaround for now. |
ya i'm working around it. |
Yes. As I said:
We simply didn't anticipate this use case and none of our beta testers had it either, so we'll have to add it. |
Should be resolved by https://github.com/reduxjs/redux-toolkit/releases/tag/v1.3.5 . |
@markerikson please could you show an example of an optional argument? That like looks like it just cancels it no? Also it seem using // someThunk.ts
export const fetchSomeThunk = createAsyncThunk(
'app/fetchSomeThunk',
async (arg: IMyArg) => {
return axios.get(url)
}
) and then in a component: // myComponent.tsx
const someThunkCall = async () => {
try {
const someThunkAction = await dispatch(someThunk(''))
unwrapResult(someThunkAction)
} catch (error) {
Bugsnag.notify(error)
}
} where as I quite liked: // someThunkOld.tsx
export const someOldSchoolActionCreator = (): Thunk => async (dispatch) => {
try {
const resp = await axios.get(url)
dispatch(someThunkSuccess(resp.data))
} catch (err) {
console.error(err)
}
} as it's all together in one place, limited duplication. It is nice having |
Uh... sorry, I'm really not sure what you're asking there, in either part of that comment. Can you clarify what you're asking? |
You mentioned: And what's the benefit of using |
I would assume that the very first comment in this thread is the "optional arg" that's being discussed: export const usersLoad = createAsyncThunk(
'users/load',
(filters: UserFilters = {}) => Api.get<User[]>('/api/users/search', filters)
); Here, the one argument to the payload creator is That means it should be legal to dispatch this thunk either with a parameter passed in: dispatch(usersLoad(someFiltersValue)); or without any parameters: dispatch(usersLoad()); The issue was that the original typings in 1.3.4 and earlier did not allow the second option to work correctly with TypeScript, and so it would yell at you if you didn't provide a value. As of 1.3.5, I'm still not entirely sure what you're asking about using I'll note that your couple thunk examples there are doing different things, so I'm not sure why you're trying to compare them as if they're identical. |
Thanks for the explanation, good clarification. Would there be a nice way to reuse |
Sorry, really having trouble understanding what you're trying to describe here :( Can you give specific examples? |
Ok no worries, so let's say I had an async thunk like this: // app/thunks
export const fetchSomeThunk = createAsyncThunk(
'app/fetchSomeThunk',
async (arg: IMyArg) => {
return axios.get(url)
}
) and I wanted to use/call it in two components: // ComponentA.tsx and ComponentB.tsx
const someThunkCall = async () => {
try {
const someThunkAction = await dispatch(someThunk(''))
unwrapResult(someThunkAction)
} catch (error) {
Bugsnag.notify(error)
}
} so I don't have to duplicate |
I guess? This is ultimately you creating your own abstraction for additional logic in a component after dispatching. |
Hmm, this feel extremely standard to me. Have you've tried to build a real-world app with |
Yes, I've worked on some "real" apps. I've just never needed to spend much time checking thunk results in components, or sending off error logs to bug reporting services, etc. My point is that what you're asking about here is really about your own abstractions, in your app. This isn't anything that is a bug, or requires API changes, or anything like that. It's your app, I don't know what your requirements are, and I don't know what use cases you're trying to solve. You're always welcome to come up with your own abstractions and use them. So, I'm not sure what advice you're looking for from me atm. |
That's ok, just trying to understand how to use it better in future 👍 no bug, thanks for the help; really appreciate it. P.s sorry for the "real" world comment, I didn't it to come across so rudely. |
Adding to this, your example above could also be written: // myComponent.tsx
const someThunkCall = async () => {
try {
- const someThunkAction = await dispatch(someThunk(''))
- unwrapResult(someThunkAction)
+ dispatch(someThunk('')).then(unwrapResult)
} catch (error) {
Bugsnag.notify(error)
}
} in the next version of RTK we are probably adding a helper so it can also be written as // myComponent.tsx
const someThunkCall = async () => {
try {
- dispatch(someThunk('')).then(unwrapResult)
+ dispatch(someThunk('')).unwrap()
} catch (error) {
Bugsnag.notify(error)
}
} which is even shorter But in the end, it is your own decision to even do all this handling in your component. You could also just have a middleware: const BugsnagMiddleware = api => next => action => {
if (isRejectedWithValue(action)) {
Bugsnag.notify(action.payload)
} else if (isRejected(action)) {
Bugsnag.notify(action.error)
}
return next(action)
} From that point on all your components would become // myComponent.tsx
const someThunkCall = () => dispatch(someThunk('')) Doing this in the component is your decision in the first place and yes that will always mean more code. |
Sorry @markerikson two further questions.
export const usersLoad = createAsyncThunk(
'users/load',
(filters: UserFilters = {}, { getState }) => {
const state = getState()
return Api.get<User[]>('/api/users/search', {
headers: {
Authorization: `Bearer ${state.auth.accessToken}`,
},
})
}
)
|
@drydenwilliams this issue really isn't a good place to provide support :( Please come by the |
I've always found this issues a bit more helpful as this was the first result on Google, so I hope it can help others if they find it due to the history? Hope that's ok; I feel like you're support is awesome! Thanks for your points @phryneas I like the idea of the middleware 👍 |
This should not be the first result on google if searching for that question, because it should never have been asked here - and by now is pretty much completely unrelated to the initial issue discussed in this bug tracker. Instead, a StackOverflow thread with a useful title and a specific problem & solution should be the first google hit. |
Not sure these points are "pretty much completely unrelated" as I can't seem to understand how to use "createAsyncThunk optional or no args" which is the issue title? Sure that might be in the wrong place now and possibly "should never have been asked here" but will be helpful now to other having a similar issue now? |
They are completely unrelated to the question if there is a way to define an The only thing they have in common is that they are about |
For anyone who comes across this in the future, I solved the no argument requirement in my TypeScript application by using the An example is below:
|
Well, it is correct, but |
Thanks for the correction @phryneas, I'm primarily a C# developer where Can you please confirm that as in version 1.6.0 of reduxjs/toolkit that the approach I have outline above is the correct way to define a think that takes no arguments i.e. having an argument defined in the |
I already said it is correct :) |
Awesome, I will use the void type. Thanks for the quick replies @phryneas! |
Seems to still be an issue with version 1.9.7 and Typescript version 5.2.2 @phryneas ...
and when I try to call it I get an error:
Workaround is to pass it an empty object
This is not ideal and a fix would be very welcomed 🙌 Fix idea you proposed @phryneas:
could very well work but a more rigid, "official" fix would be better imo. |
For me |
I am trying to make an api call with an optional parameter however typescript complains
Expected 1 arguments, but got 0
I have a similar issue with this action
here I don't use the arg but I had to give it the SyntheticEvent or it complained when passing it to onClick, and I had to give it void to make it work when I call it directly. I would think that I would not have to set it to anything since I am not using it.
The text was updated successfully, but these errors were encountered: