async call with reducer not work - javascript

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

Related

Is dispatch needed in an action in redux?

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).

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

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.

Why use redux-thunk? [duplicate]

This question already has answers here:
Why do we need middleware for async flow in Redux?
(12 answers)
Closed 5 years ago.
I don't understand the need for something like redux-thunk. From what I understand a thunk is a function which returns a function. The wrapped expressions and the use of middleware appear to me to do more to obfuscate what is happening. Taken from redux-thunk's sample code
import thunk from 'redux-thunk';
// Note: this API requires redux#>=3.1.0
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
// Meet thunks.
// A thunk is a function t hat returns a function.
// This is a thunk.
function makeASandwichWithSecretSauce(forPerson) {
// Invert control!
// Return a function that accepts `dispatch` so we can dispatch later.
// Thunk middleware knows how to turn thunk async actions into actions.
return function (dispatch) {
return fetchSecretSauce().then(
sauce => dispatch(makeASandwich(forPerson, sauce)),
error => dispatch(apologize('The Sandwich Shop', forPerson, error))
);
};
}
// Thunk middleware lets me dispatch thunk async actions
// as if they were actions!
store.dispatch(
makeASandwichWithSecretSauce('Me')
);
The above code could be written far more concisely and intuitive:
fetchSecretSauce().then(
sauce => store.dispatch(makeASandwich('Me', sauce)),
error => store.dispatch(apologize('The Sandwich Shop', forPerson, error))
)
My question is what need is redux-thunk fulfilling and how does it improve on existing solutions similar to the example above.
Redux Thunk teaches Redux to recognize special kinds of actions that are in fact functions.
When an action creator returns a function, that function will get executed by the Redux Thunk middleware. This function doesn't need to be pure; it is thus allowed to have side effects, including executing asynchronous API calls. The function can also dispatch actions.
The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met.
If Redux Thunk middleware is enabled, any time you attempt to dispatch a function instead of an action object, the middleware will call that function with dispatch method itself as the first argument.
And then since we “taught” Redux to recognize such “special” action creators (we call them thunk action creators), we can now use them in any place where we would use regular action creators.
Check this great answer from Dan Abramov himself, it covers everything: https://stackoverflow.com/a/35415559/5714933
Also check these links for more info:
https://github.com/gaearon/redux-thunk#motivation
http://redux.js.org/docs/advanced/AsyncActions.html

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