I'm trying to learn redux and the tutorial I'm following along has the following syntax in the userActions file
export const loginUser = (userData) => (dispatch) => {
dispatch({type: 'something'})
}
However when we call the loginUser function (in another file) the syntax is like this
this.props.loginUser(userData)
I was wondering where does the dispatch come from? Why don't we get dispatch is undefined for calling it in this manner
The dispatch function is made available because you're using redux-thunk, which is a redux middleware. And because of this middleware, your action is able to fire multiple dispatch to your reducer.
dispatch function comes from connect function of react-redux. Connect function receives mapStateToProps and mapDispatchToProps.
With mapStateToProps, redux map state from reducer to this.props of your component
With mapDispatchToProps, redux will call a function like login, after login redux will dispatch an action with some new states(optional) to let you know login success or failed. Those states will be passed into your component through mapStateToProps
Redux is a state container which is used to have a global state which can be access from all over the project. so we have to inform the global container about our state changes such as create,delete and updates. To inform the changes we use dispatch and we provide a referring name called type. in some cases we pass the data also to dispatch with the referring name of payload.
the first function you wrote was trying to login with the user data. the function is needed to be called in login component. so we pass the function as prop to the login component. now the login function is in your props so simply call is as
this.props.loginuser(userdetails)
Related
suppose if i dispatch an action using dispatch() , i know that reducer() is called which has an action object and current state as parameters . i want to know what calls that reducer function ? which functions are called before reducer function and after dispatch function ? after reducer function returns the new state ,which functions are called after that ? where does this new state goes ? does usestate() and useselector() also returns something after reducer function returns new state ?
i want to know what calls that reducer function ?
which functions are called before reducer function and after dispatch function
dispatch() indeed 'call' every reducers. It uses an event system and all reducers are listening to this event (this is all behind the scene).
Still, you can write a piece of code that will be inserted between the dispatch call and the reducers catching actions.
It's called a middleware.
A middleware can intercept any action triggered by a dispatch, also it has access to the store.
At the end of your middleware your just use a callback to tell the flow to continue.
You need to pass your action to it so your reducers can finally be called and receive the action.
Here is an example of middleware that log any actions that are sent by any dispatch()
const logger = store => next => action => {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
To make it work you need to pass your middleware to your redux configuration, so they can be called.
after reducer function returns the new state ,which functions are
called after that, where does this new state goes ?
If you look at your redux configuration you'll see somewhere that you combine all of your reducers ( often called root reducer).
const combinedReducers = combineReducers({ reducerA, reducerB })
const store = createStore(combinedReducers )
Redux use this combination of reducers to fill the store, so anytime a reducer return it's result, it can be save in 'the store'
does usestate() and useselector() also returns something after reducer function returns new state ?
useSelector() is a hooks that has the ability to read in the store. (Store that contains the fresh result of your reducers and is updated every time there is a modification in the store)
useState() is not related to redux. It's related to React. With useState you can read and write in the local state of a component.
It returns you a piece a your state and a setter for this piece of state.
const {myPieceOfState, setMyPieceOfState} = useState({ something :'a default value for myPieceOfState'})
Here's a simple case, I want to create a generic Modal component with a confirm button. Once the button was clicked, it will fire the onConfirm function we provided via the redux state. And the openModal action can be dispatch inside a thunk action.
//Example using thunk after click submit a form
const handleSubmitForm = dispatch => e => {
dispatch(openModal({
title: "confirm modal",
onConfirm: () => { /* dispatch other stuff, async etc..)*/ }
}))
}
However, the issue is that the redux suggest not to pass any non-serializable value like function to the state. And when using redux-toolkit, it will generate a error message "A non-serializable value was detected in the state". So I wonder what is the best practice to perform this type of action.
Other use case:
dispatch a callback function to the state and contact a web socket server. Then the websocket server communicate back with something that trigger the callbcak.
Simple Modal CodeSanbox: https://codesandbox.io/s/black-mountain-wnytg?file=/src/containers/App.js
The best practice is not to do store any functions in redux (though it will technically work). Instead you should store whatever arguments you need to invoke the callback and use an action creator function to actually make the call. In your example you might store modalType, modalTitle, etc.
I am new to react and redux. I have gone through many online tutorials on react redux but still not able to understand how action and reducer is connected. If I am right, we import action in container/component, we import reducer in a file where we create a store. So there is a connection between container - action, and there is a connection between reducer and store but in action file we dont import reducer. So how action is connected to reducer. I know that we have a type of action which will be checked in switch case in reducer. But how does it get passed to reducer.
Very High Level Overview
Action - Actions can update state
{ type: ACTION_TYPE, somePayload: payload }
The redux store exposes out a dispatch function, that ultimately wraps an action creator.
mapDispatchToProps = dispatch => {
return {
someWrappedAction: () => dispatch(actionCreatorFn()),
someOtherWrappedAction: val => dispatch(otherActionCreatorFn(val)),
}
}
useDispatch Hook returns the dispatch and you wrap action yourself
const dispatch = useDispatch()
<button onClick={() => dispatch(someActionCreatorFn())}>
Do Action
</button>
Reducer
The reducers form a state tree, starting with the root reducer passed to the redux store. The "connection" is made (conventionally) via the mapDispatchToProps and connect HOC. (Now can get the dispatch from useDispatch hook)
Reducers are pure functions that take two arguments, current state and an action, and returns the next state.
(currentState, action) => nextState
So how is each dispatch in mapDispatchToProps connected to the appropriate reducer...
When you dispatch an action creator it passes the action object to the root reducer. The action object is passed through the entire state tree and any reducers that process the action type consume it.
TLDR: dispatch function takes action as an argument and calls currentReducer(..., action).
When you call creteStore(reducer), the returned object contains dispatch and subscribe functions.
When you (or react-redux library) call subscribe(listener), redux will remember your listener function (in case of React, the listener has to make sure the component re-renders with new props, context, state, or refs - depending on concrete implementation).
When dispatching an action with dispatch(action), the dispatch function will call reducer(action, state), modify redux internal currentState then call each listener().
I have come across this piece of code while learning react-redux
export const mapDispatchToProps = (dispatch, getState) => {
return ActionCreators({completeDriver}, dispatch, getState);
};
I want to know when to use this function.
as per redux actions are dispatched like dispatch(actionCreator())
for doing so inside an react component you need the reference of dispatch which need to be passed as prop to your component.
so if you use connect() you can reduce this passing of dispatch as prop by yourself this thing will be handed via connect HOC(Higher Order Component).
for larger scale application using mapDispatchToProps of connect would saves lot of dev time of wiring things.
I'm looking through the auth0 sample project for using react, redux and auth0 for a login scenario here. However I'm a bit confused about this particular example where we call this.props.doAuthentication()
// App.js
import { loginUser, fetchQuote, doAuthentication, fetchSecretQuote } from '../actions'
// add a constructor
constructor(props) {
super(props)
this.props.doAuthentication()
}
Here is the action definition
// actions.js
...
const lock = new Auth0Lock('YOUR_CLIENT_ID', 'YOUR_CLIENT_DOMAIN');
export function login() {
// display lock widget
return dispatch => {
lock.show();
}
}
// Listen to authenticated event and get the profile of the user
export function doAuthentication() {
return dispatch => {
lock.on("authenticated", function(authResult) {
lock.getProfile(authResult.idToken, function(error, profile) {
if (error) {
// handle error
return dispatch(lockError(error))
}
localStorage.setItem('profile', JSON.stringify(profile))
localStorage.setItem('id_token', authResult.idToken)
return dispatch(lockSuccess(profile))
});
});
}
}
...
I'm new to redux so maybe this is an obvious answer but
Where is doAuthentication bound to the the props in App.js? Assuming that App.js is the top level root app component.
Doesn't doAuthentication generate a function that expects a dispatch argument? Why don't we do anything in the constructor with the returned function from doAuthentication()? If we don't assign the returned function to anything, does this.props.doAuthentication persist anything or have any effects? Shouldn't it be something like doAuthentication()(someDispatchFunction) Where does this dispatch function come from?
1.Where is doAuthentication bound to the the props in App.js? Assuming that App.js is the top level root app component.
Ans:
The action doAuthentication is bound with the props of App component using the middleware called redux-thunk.
let createStoreWithMiddleware = applyMiddleware(thunkMiddleware, api)(createStore)
let store = createStoreWithMiddleware(quotesApp)
The above two line of code would have done it for your. Read here why redux-thunk is required.
2.Doesn't doAuthentication generate a function that expects a dispatch argument? Why don't we do anything in the constructor with the returned function from doAuthentication()? If we don't assign the returned function to anything, does this.props.doAuthentication persist anything or have any effects? Shouldn't it be something like doAuthentication()(someDispatchFunction) Where does this dispatch function come from?
Ans:
2.1 Yes, the function which is returned by doAuthentication function expects a dispatch method as to be a first parameter.
2.2, 2.3 Here the doAuthentication action creator's job is to create a Redux action which would just listen for the event called authenticated. When we call doAuthentication action creator, it returns a Redux action function which accepts a dispatch method as first parameter and getState method as second. The parameters would be passed by the redux-thunnk middleware.
The redux-thunk middleware would call the redux action which is return from the doAuthentication call since it is connet-ed. Otherwise we have to dispatch the action returned by the doAuthentication as like the below,
this.props.dispatch(doAuthentication())
2.4 We can do as you mention doAuthentication()(someDispatchFunction), but consider this quote
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, you can find a detailed info about the redux-thunk with this answer