Do I need to await an async Redux Thunk (not Promise)? - redux

Assume this is my thunk:
const thunk = async (dispatch,getState) =>{ 'some dispatch and await code'}
So when I want to dispatch this thunk, should I use await dispatch(thunk) or just dispatch(thunk)?
From the source code of Redux-thunk and Redux, I think I should use await dispatch(thunk) as redux-thunk won't add that 'await' for me. But what happened if I don't use await (it just return a pending Promise), will the code inside thunk (dispatch and pull from Api etc.) still get executed?
Thanks

That highly depends if you want to do something afterwards.
If you just want to dispatch that thunk and have it go, you can just dispatch it.
Your next line of code will run immediately after the thunk started, not waiting for it to finish.
Or you can choose to await it, then your next line of code will only continue running after the thunk finished or failed.

Related

How to make the watcher saga fire a worker saga only on the first dispatch on an action pattern?

How to make the watcher saga fire a worker saga only on the first dispatch on an action pattern?
function* rootSaga() {
yield takeEvery(CHATBOT.START, handleChatbotLoad); //I want watcher saga to trigger handleChatbotLoad only on the very first dispatch of CHATBOT.START
yield takeEvery(CONVERSATION.ADD_QUERY, handleUserInput);
}
So ya, I want watcher saga to trigger handleChatbotLoad only on the very first dispatch of CHATBOT.START. I can have a flag in the state like started and dispatch CHATBOT.START only once.
But then I was expecting a method like takeFirst or something like that. Is there any such method to achieve this?
You can call (or spawn, fork) some function in root saga, which means it'll be called only once when app started. And use take in this function to wait for action dispatched:
function* onlyVeryFirstStartWatcher() {
const action = yield take(CHATBOT.START);
// started, do stuff...
yield call(handleChatbotLoad);
}
function* rootSaga() {
yield takeEvery(CONVERSATION.ADD_QUERY, handleUserInput);
yield call(onlyVeryFirstStartWatcher)
}

Post request redux thunk

I have GET requests and normally when those succeeded I save data in store, but for POST requests I need to know if it succeeded or not, in order to execute some code (show a message and redirect), the docu says you can use an isLoading variable, but it just says if the service is working but not if it succeeded, if I try to create a new success variable in the store, it will be turned on forever after the request and I don't need that either. I tried returning a promise from the action creator and handle response directly inside the component but it looks like the same to call axios there instead of using redux.
My action creator looks like this:
export function createProject(userId, projectName) {
return function (dispatch) {
dispatch({ type: projectsActions.START_CREATE_PROJECT });
return ProjectsService.createProject(userId, projectName).then(() => {
dispatch({ type: projectsActions.SUCCESS_CREATE_PROJECT });
}).catch((error) => {
dispatch({ type: projectsActions.ERROR_CREATE_PROJECT });
throw error;
});
}
}
I understand where your doubts are coming from, it doesn't seem appropriate to have a field on your Redux store only to know the success of a one-time request.
If you only need to make a post request and only care about it's result once, the simplest way to do it is to use state in the component making the request. Component-level state is easily manageable and gets removed from memory when the component is unmounted, but on the other hand you may want to have a single source of truth for your app. You have to make a choice, but your Redux implementation is correct.

How to make a couple of async method calls in django2.0

I am a doing a small project and decided to use Django2.0 and python3.6+.
In my django view, I want to call a bunch of REST API and get their results (in any order) and then process my request (saving something to database).
I know the right way to do would be to use aiohttp and define an async method and await on it.
I am confused about get_event_loop() and whether the view method should itself be an async method if it has to await the response from these methods.
Also does Django2.0 itself (being implemented in python3.6+) have a loop that I can just add to?
Here is the view I am envisioning
from rest_framework import generics
from aiohttp import ClientSession
class CreateView(generics.ListCreateAPIView):
def perform_create(self, serializer):
await get_rest_response([url1, url2])
async def fetch(url):
async with session.get(url) as response:
return await response.read()
async def get_rest_response(urls):
async with ClientSession() as session:
for i in range(urls):
task = asyncio.ensure_future(fetch(url.format(i), session))
tasks.append(task)
responses = await asyncio.gather(*tasks)
Technically you can do it by loop.run_until_complete() call:
class CreateView(generics.ListCreateAPIView):
def perform_create(self, serializer):
loop = asyncio.get_event_loop()
loop.run_until_complete(get_rest_response([url1, url2]))
But I doubt if this approach will significantly speed up your code.
Django is a synchronous framework anyway.

Redux redirect using redux-thunk

Hey guys I have a function as so:
function dispatchSignup(username, password) {
return function(dispatch) {
const newUser = {username: username, password: password}
axios.post('/signup', newUser).then(() => {
return dispatch(signupAction)
}).then(() => {
return dispatch(push('/'))
}).catch((error) => {console.log(error)})
}
}
This function is first sending a request to my server to signup. If successful, '.then' runs and dispatches a signupAction. I then call another '.then' after this, which should only run after this signupAction has been dispatched, which will redirect the user to '/' aka. my home page. The problem I'm having, is that yes they signup, and the url pushed works, however it's not actually rendering the component at '/'. What is happening here? It's as if they're blocking one another, although I'm not really sure. Redux-thunk is async I thought, so the second action I call won't be dispatched until the first has successfully dispatched.
Any help would be greatly appreciated, thanks.
I then call another '.then' after this, which should only run after this signupAction has been dispatched
This assumption is incorrect. The dispatch function returns the action being dispatched, not a Promise. Assuming signupAction is also using redux-thunk (returning an action), then that would explain why your call to push('/') is happening immediately and not waiting for your signup process to be complete.

Tests with redux async action and axios

I have been learning testing with
mocha
chai
sinon
enzyme
now I am testing a redux async application, and I want to know if the arguments provided to some API calls are correct, how do I do that?
I'm thinking of something like axios.getCall().args to get the arguments provided for the API call and then verify if they are correct but I can't find a command that matches what I am thinking.
I found out how,
first stub the method
axios.post = sinon.stub().returns(Promise.resolve({ data: 'test' }));
then dispatch the async action
store.dispatch(updateTodos(currentState))
.then(() => {
// this line would get the call and then get the argument
let args = axios.post.getCalls()[0].args;
done();
});

Resources