Call multiple dispatch after getting axios response Redux - reactjs

I need to call multiple dispatches after getting the response from axios how can I do, it the current way I'm doing is only allowing me to send one dispatch and when trying to fire the second dispatch it gives and error saying that the res is not found.
export const getItem = (id) => dispatch =>{
dispatch(setLoading);
axios.get(`http://localhost:8081/getItem?id=${id}`)
.then(
res => dispatch({
type: GET_ITEM,
payload: res.data
})
)
}
I need to fire a secondary dispatch after getting the response, the functionality of the secondary dispatch, I need to this after getting the return from axios is because a unique email and id is stored in the response, so I need to get the id, from the response to fire the secondary call.
export const getUserItem = (payload) => dispatch =>{
dispatch(setItemsLoading);
axios.get(`http://localhost:8081/getUserItems?email=${payload.email}&id=${payload.id}`)
.then(
res => dispatch({
type: GET_USER_ITEM,
payload: res.data
})
)
}
Is there a way to dispatch 2 after a response is received from axios?

With arrow syntax you need to add brackets if you want to do more than a single statement:
export const getItem = (id) => dispatch =>{
dispatch(setLoading);
axios.get(`http://localhost:8081/getItem?id=${id}`)
.then(
res => {
dispatch({
type: GET_ITEM,
payload: res.data
})
//second dispatch
dispatch({
type: GET_ITEM,
payload: res.data
})
}
)
}

Related

The function call inside the redux action doesnot get executed

I'm trying my first react application with redux, along with Thunk as middle ware. When calling the action from one of the components, the action is hit but the code inside the action return is not executed. I have no clue what I'm missing here. I'm also using Firestore to get the data.
export const getBikeTypes = () => {
console.log('outside return')
return (dispatch, getState, { getFireBase, getFireStore }) => {
console.log('inside return')
const firestore = getFireStore();
firestore.collection('BikeTypes').get()
.then((response) => {
console.log(response)
return response
}).then(() => {
dispatch({ type: 'GET_BIKETYPES' });
}).catch((err) => {
dispatch({ type: 'GET_BIKETYPES_FAIL', err });
})
}
};
I think you should dispatch action with the payload once you get the response.
const firestore = getFireStore();
firestore.collection('BikeTypes').get()
.then((response) => {
dispatch({ type: 'GET_BIKETYPES', payload: response })
})

How to pass parameters in an async api thunk call

Hi I am trying to pass a parameter for the post method in an api call in a redux thunk middleware. But this is not invoking an action. Could someone have a look at the code and tell what mistake i am doing:
import API from "../../_metronic/utils/api";
let FetchActions = async (id,dispatch) => {
await API.post("companies/",id)
.then(res => dispatch({ type: "FETCH_COMPANIES", payload: res.data }))
.catch(err => console.log(err));
};
export default FetchActions;
I am getting the following error:
TypeError: dispatch is not a function
at fetchAction.js:6
import API from "../../_metronic/utils/api";
let FetchActions = id => async (dispatch, getState) => {
await API.post("companies/",id)
.then((res) => {
dispatch({ type: "FETCH_COMPANIES", payload: res.data })
})
.catch((err) => {
console.log(err)
});
};
export default FetchActions;
You are doing wrong with the syntax as redux-thunk needs a callback function to return from the method.
Another thing is if you are using await you don't need to have .then and .catch, instead, you should wrap this code in the try-catch block.
The below code should work for you.
import API from "../../_metronic/utils/api";
let FetchActions = async (id) => {
return async (dispatch, getState) => {
try {
const res = await API.post("companies/",id);
dispatch({ type: "FETCH_COMPANIES", payload: res.data })
} catch(err) {
console.log(err)
}
}
};
export default FetchActions;
Read more about the action creators in redux-thunk here.

React Redux Call action within action and get return value

I am trying to call and action from an action to get a database record by name, then I want to use the ID of the role record in the SignUp action that is currently being called .
How can I reuse the code for my GetRolebyName action from within the sign up action, I was trying to avoid doing the same APi request in two places.
Essentially I am just trying to look up the RoleId when creating a user.
Role actions:
export const fetchRoleByName = name => async dispatch => {
const response = await db.get(`/roles?name=${name}`);
dispatch({
type: FETCH_ROLE,
payload: response.data[0]
});
};
Sign up Action:
export const signUp = values => async (dispatch, getState) => {
const role = await dispatch(fetchRoleByName(values.userType))
const response = await db.post('/users/',
{
...values,
roleId: role.id
}
);
dispatch({
type: SIGN_UP,
payload: response.data
});
history.push('/');
};
Solution:
As pointed out by Kaca992, the fetchRoleByName action never actually returned anything so the change required was as per below;
export const fetchRoleByName = name => async dispatch => {
const response = await db.get(`/roles?name=${name}`);
const data = response && response.data && response.data[0];
dispatch({
type: FETCH_ROLE,
payload: data
});
return data;
};
Inside fetchRoleByName just return response. Return from dispatch is the return value of the inner function:
export const fetchRoleByName = name => async dispatch => {
const response = await db.get(`/roles?name=${name}`);
dispatch({
type: FETCH_ROLE,
payload: response.data[0]
});
return response; (or return response.data[0] if that is the role object you want, but then I would recommend writing it like this: response && response.data && response.data[0] just in case of hitting an unexisting value from db)
};
Hope this helps.

Why are action function called wrapped inside dispatch in react?

I was just going through some react-redux code online and basically i came across the following set of code , which is basically a js file full of ACTIONS , just to give some context a combination of redux and redux-thunk is being used here:
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
await dispatch(getConfig());
await dispatch(getGenres());
dispatch({ type: TYPES.REMOVE_LOADING });
};
// Action Creator to get the config object from the API
export const getConfig = () => async dispatch => {
const res = await tmdbAPI.get('/configuration');
dispatch({
type: TYPES.GET_CONFIG,
payload: res.data,
});
};
I am a bit confused as to why is getConfig function is being wrapped inside a dispatch ?
if you don't want, don't wrap that
like this
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
dispatch(await getConfig());
dispatch({ type: TYPES.REMOVE_LOADING });
};
//this is not using redux-thunk
// Action Creator to get the config object from the API
export const getConfig = async () => {
const res = await tmdbAPI.get('/configuration');
return {
type: TYPES.GET_CONFIG,
payload: res.data,
};
};
Important
but there are so many reasons why wrap the actions by dispatch.
Here is one example.
when you want get multiple data in one action step by step
export const getData = () => async dispatch => {
dispatch({
type: DATA_LOADING_START
});
try {
const res = await tmdbAPI.get('/url1');
dispatch({
type: DATA1_LOADED,
payload: res.data,
});
const res = await tmdbAPI.get('/url2');
dispatch({
type: DATA2_LOADED,
payload: res.data,
});
} catch (err) {
// handle error
}
dispatch({
type: DATA_LOADING_END
});
};
//this is using redux-thunk
#AlexanderSolonik
Question: Why wrap actions by dispatch?
because dispatch() sends the action result to the reducer.
Redux thunks are just redux actions that can perform side effects. So
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
await dispatch(getConfig());
await dispatch(getGenres());
dispatch({ type: TYPES.REMOVE_LOADING });
};
Is just an async init function which when called performs the steps in a synchronous manner.
The key is that thunks can dispatch other thunks/actions/etc so the init thunk is just dispatching the getConfig() action which is itself async so the next step of the init function won't be performed until the config API call finishes (possibly because some other code depends on it)

Call action based on redux props received from another action

This sounds a little odd (I'm new to react/redux) but let's say I have a component in which I call an action like so:
componentDidMount() {
this.props.getTask(this.props.match.params.id);
}
This action called here populates the redux state with some data related to the task (title, description etc.) What it also has is an id of another element which I need in order to call another action like so:
this.props.getSomethingElse(this.props.task.something._id);
The problem:
In componentDidMount I call the first action and I want to call the second action after I received the data from the first one because as I mentioned I need that id. How should I approach this? What's the best practice in this case?
EDIT: Redux action below.
//GET Task
export const getTask = id => dispatch => {
dispatch(setTaskLoading());
axios
.get(`/api/tasks/${id}`)
.then(res => {
dispatch({
type: GET_TASK,
payload: res.data
});
})
.catch(err =>
dispatch({
type: GET_TASK,
payload: null
})
);
};
React components should not orchestrate multiple redux calls. Calls should be dispatched because of user interaction, or life cycle (mount/unmount).
If you have actions that are dependent on other actions, you can combine them using a middleware (thunk for example) or sagas.
In this case, since getTask is a thunk, you can use it to dispatch multiple actions that can use the data returned from the async (axios) request:
//GET Task
export const getTask = id => dispatch => {
dispatch(setTaskLoading());
axios
.get(`/api/tasks/${id}`)
.then(res => {
dispatch({
type: GET_TASK,
payload: res.data
});
// getSomethingElse
dispatch({
type: GET_SOMETHING_ELSE,
payload: res.data.something.id
});
})
.catch(err =>
dispatch({
type: GET_TASK,
payload: null
})
);
};

Resources