Is dispatch needed in an action in redux? - javascript

I've been learning redux for some time now and was wondering why is the dispatch needed in an action, cant we just use return, is that not the same thing?
return {
type: SEARCH_MOVIE,
payload: text,
};
};
export const fetchMovies = (text) => (dispatch) => {
axios
.get(`https://www.omdbapi.com/?apikey=${APIKey}&s=${text}`)
.then((response) =>
dispatch({
type: FETCH_MOVIES,
payload: response.data.Search,
})
);
};
The first action is without the dispatch and its working normally, why do we need to use dispatch in the other function cant we just use return? I just need someone to explain to me what dispatch does inside an action that im gonna dispatch anyway later in my component somehow or onClick.Why do we need to dispatch it twice?

That is a thunk when using the redux-thunk library.
With a plain basic Redux store, you can only do simple synchronous updates by dispatching an action. ...
Thunks are the recommended middleware for basic Redux side effects logic, including ... simple async logic like AJAX requests.
action, in the redux vocabulary, is just an object, e.g. {type: 'a1'},
action creator is a function that returns an action, e.g.
(value) => ({type: 'a1', valye})
thunk of action is a function that takes dispatch function as an argument and calls it, e.g.
(dispatch) => { dispatch({type: 'a1'}) }. With the redux-thunk middleware, it can be used in any place where action is expected.
thunk of action creator is a function (a) that returns a function (b) so that (b) is a thunk of action crated within a closure of (a), e.g.
(value) => (dispatch) => { dispatch({type: 'a1', value}) }
When using redux-thunk, the simple action creator and the thunk of an action creator can be used interchangeably, you don't have to use (dispatch) => ... when not needed (it is needed for asynchronous operations or more complex logic with multiple actions dispatched from one function).

Related

Why does redux thunk return promise?

I am learning redux-thunk middleware as a beginner react developper, and I don't understand why dos the function (returned by redux-thunk) returns a promise (returned by fetch())
I tried not to return anything, and it worked, so why do we return it?
export function getCourses() {
return fetch(baseUrl)
.then(handleResponse)
.catch(handleError);
}
export function loadCourses() {
return function(dispatch) {
dispatch(beginApiCall());// dispatch some synchronous action
return courseApi
.getCourses().then(courses => {
dispatch(loadCourseSuccess(courses));
}).catch(error => {throw error;});
};
}
For the component named MyComponent dispatching loadCourses() action
function MyComponent(props){
.......
useEffect(() => {
loadCourses()
});
const mapDispatchToProps = {
loadCourses,
.....
}
}
I think i got the answer(from a colleague).
if you want to chain certain activities, your action would need to return a Promise.
it's just a good way to allow chaining activities after the result is returned!
Well, first of all the function returns some data because you asked it to return some sort of result return function(dispatch) {...}.
If you want to ignore the returned result just remove the return from return function(dispatch) {...}.
Secondly, the function returns a promise because of the way that you have written your call to API functions (wrapped inside promise and not returning callbacks upon function completion).
If you want to get the actual result of the API call you should use the Async / Await syntax.
With a plain basic Redux store, you can only do simple synchronous updates by dispatching an action. Middleware extends the store's abilities and let you write async logic that interacts with the store.
Thunks are the recommended middleware for basic Redux side effects logic, including complex synchronous logic that needs access to the store, and simple async logic like AJAX requests.https://github.com/gaearon/redux-thunk
The thunk middleware knows how to turn thunk async actions into actions, so you just have to have your simple_action() to be a thunk and the thunk middleware will do the job for you, if the middleware see a normal action, he will dispatch this action as normal action but if it's an async function it will turn your async action into normal action.
You can also see return promise from store after redux thunk dispatch

How to implement post api calls using thunk middleware in react-redux?

I was working with redux-thunk and superagent npm for jwt authentication and i would want to know how to implement post calls using thunk-middleware in the actions.js file and not in the main reducer.js file
There's a couple of different ways to go about it, but I personally like to use the axios library. Axios essentially just assists with making an API request and parsing the data back from the API into json.
In your actions.js file.
export const authenticateUser = () => {
return (dispatch, getState) => {
//get the token from the reducer
const jwtToken = getState().jwtTokenReducer.tokenKey
axios.post("/api/authenticate-user", jwtToken) //jwtToken passed into request
.then((res) =>){
dispatch({
type: "AUTHENTICATE_USER",
payload: res.data
})
}
.catch((errors) => {
dispatch({
type: "ERRORS",
payload: errors.response.data
})
})
}
}
So take a look at the above syntax. Typically when you define an action-creator, you setup a function that returns an action (object). But thanks to redux-thunk, you can now setup your action-creators to return functions with dispatch as an argument.
So in your returned function you can define certain logic, like making a request to an API like we did up there. Then we can take that data by using the .then promise handler and use it as a payload for an action that we would explicitly dispatch to our reducers.

use of redux-thunk with redux-observable

I'm using redux-thunk to manage async stuff in my react application and I want to use redux-observable to manage complex async flow more easily (concat multiple Ajax calls for example). Is there a way to do so without modify what's already done?
Here's an example of what I mean:
const fetchSomeData = () => {
return (dispatch, getState) => {
doAnAjaxCall((err, response) => {
if (err) return dispatch({type: 'ERROR', err})
// do something
return dispatch({type: 'SUCCESS', response})
})
}
}
Is it possible to use fetchSomeData inside an epic?
Since redux-thunk is promise based redux-observable should allow that, am I missing something?
Yep! You totally can use them together. Just place the redux-thunk middleware before the redux-observable middleware.
applyMiddleware(thunkMiddleware, epicMiddleware)
https://stackblitz.com/edit/redux-observable-playground-8c7pd9?file=ping-pong.js
Redux applies middleware in the order they are provided as arguments, so in this case we want the thunk middleware to absorb any dispatched thunks so that the thunk functions themselves never reach redux-observable (only pure actions). But your epics can still dispatch thunks since the redux-observable middleware uses store.dispatch under the hood.

async call with reducer not work

i'm trying to implementing a Redux action that retrieves some json data with an asynchronous call using React Native. I put the function fetchRestaurant() everywhere inside component but i still get this error:
Cannot read property 'type of undefined.
here's the code inside action/restaurant.js
export function setFetchedRestaurant(restaurants){
return Object.assign({ type: types.SET_FETCHED_RESTAURANT, restaurants:restaurants } );
}
export function fetchRestaurant(){
var restaurants;
fetch('https://appetizing.000webhostapp.com/connect.php').then((response) => response.text()).then((responseText) => { dispatch(setFetchedRestaurant(JSON.parse(responseText)));}).catch((error) => {console.warn(error);});
}
and this is my call to fetchRestaurant() function inside my component:
componentDidMount(){
this.props.fetchRestaurant();
}
You need to use middleware to handle the asynchronous action. One such middleware is Redux thunk.
Here is your action creator written as a Redux thunk:
export function fetchRestaurant() {
return (dispatch) => {
var restaurants
fetch('https://appetizing.000webhostapp.com/connect.php')
.then((response) => response.text())
.then((responseText) => {
dispatch(setFetchedRestaurant(JSON.parse(responseText)));
})
.catch((error) => {
console.warn(error);
});
}
}
redux-thunk
Remember for this to work you will to insert redux-thunk into your middleware chain when configuring your Redux store
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
How does a Thunk Action creator work?
This single thunk action creator is an action creator that will be handled by our redux thunk middleware since it fits the signature associated with thunk action creators, that is it returns a function.
When store.dispatch is called our actions will go through the middleware chain before they reach the store. Redux Thunk is a piece of middleware that will see our action is a function and then give this function access to the stores dispatch and get state.
Here is the code inside Redux thunk that does this:
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
Okay so that is why our thunk action creator returns a function. because this function will be called by middleware and give us access to dispatch and get state meaning we can dispatch further actions at a later date.
Remember redux-thunk is not the only solution. if we wanted to dispatch promises instead of functions we could use redux-promise. However I would recommend starting with redux-thunk as this is the simplest solution.
redux-promise
An alternative method to redux thunk for handling your async Redux actions is redux-promise. Instead of action creators that return a function you can dispatch action creators that return a promise.
Here is an example:
function actionExample(payload){
return new Promise( (resolve, reject) => {
resolve(data);
});
}
You can of course combine redux-promise and redux-thunk middleware so that you can dispatch functions that when called dispatch promises

react, redux chain a next dispatch

I'm still beginning in react and redux and now I followed this tutorial and it uses this middleware for dispatch. I was wondering how I would do another dispatch after the first one (to chain it)? I have something like this now.
fetchData() {
const { dispatch } = this.props;
const action = PageActions.fetchPage({slug: this.props.params.slug});
dispatch(action);
}
and wondering if I can dispatch(action).then(...) but the return of dispatch is always undefined. Is that possible?
If you would like to use async actions inside of your action creators you need to use middleware. The recommended middleware is thunk.
There is a good post on Stack about it's usage and appropriate situations. Stack Overflow Async Actions
This will allow you to dispatch many actions from a single action. However if you are wanting to "chain" actions together you should simply dispatch the second action at the end of the first actions definition.
ie
function getBookings() {
return (
RequestHelper.fetchEntities(Routes.bookings.all, {}, queryParams)
.then(res => dispatch(getBookingsSuccess(res));
)
}
...
function getBookingsSuccess(data) {
dispatch(showSuccess());
}

Categories