redux mapStateToProps call ajax incase of empty state - reactjs

Using redux in react, how can I dispatch an action from inside the mapStateToProps function ?
class Example React.Component {
render(){return (
<div>
Hello {this.state.userData.name} <--
</div>)};
);
Example.propTypes = {
id: PropTypes.number.isRequired,
};
function select(state,ownProps) {
let userData = state.user[ownProps.id];
if(!userData){//if not already in store then i want to load it
///I WANT TO dispatch an action that load this user from server.
//dispatch({type:'LOAD_USER',id: ownProps.id});
}
return {
userData
};
}
export default connect(select)(Example);
//example usage <Example id="1" /> //should return state.user[1].name

Since your component rendering is very dependent on the user data being called by ajax, the right place to dispatch would be componentWillReceiveProps.
If you have passed in a mapDispatchToProps callback to connect(), then you should be able to call this.props.actions.anyAction() within componentWillReceiveProps.
If you had called connect() without passing in the second parameter (mapDispatchToProps), then you'll have to explicitly call this.props.dispatch()

I'd highly recommend to use sagas for asynchronous tasks.
Have a saga watch for this action.
If it sees one, let it check if the user is in store.
If he is not in store, make an asynchronous action to get it, add it to the store, and replay the previous action.

Related

What is going on in this Redux code...confused about mapDispatchToProps, dispatch, and connect

I'm following a react tutorial and I had a few questions.
I am confused about this function:
function mapDispatchToProps(dispatch) {
return bindActionCreators({ fetchWeather }, dispatch)
}
I want to breakdown each part of this function.
How do you hook up the action creator to a container? How is this.props.fetchWeather working code? Is this responsible for that?:
function mapDispatchToProps(dispatch) {
If so, what is this doing?
return bindActionCreators({ fetchWeather }, dispatch)
Is that responsible for making sure that the action object that is returned from the action creator flows down into the middleware and reducers?
What is this doing then:
function mapDispatchToProps(dispatch)
Is mapDispatchToProps just convention or is it part of react?
Lastly, what is this export doing:
export default connect(null, mapDispatchToProps)(SearchBar);
What is the connect doing? What does it do for me?
Here is my whole code for reference:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchWeather } from '../actions/index';
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = { term: '' };
this.onInputChange = this.onInputChange.bind(this);
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onInputChange(event) {
this.setState({ term: event.target.value });
}
onFormSubmit(event) {
event.preventDefault();
this.props.fetchWeather(this.state.term);
this.setState({ term: '' });
}
render() {
return (
<form onSubmit={this.onFormSubmit} className="input-group">
<input
placeholder="Get a five-day forecast in your favorite cities"
className="form-control"
value={this.state.term}
onChange={this.onInputChange}
/>
<span className='input-group-btn'>
<button type="submit" className="btn btn-secondary">
Submit
</button>
</span>
</form>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ fetchWeather }, dispatch)
}
export default connect(null, mapDispatchToProps)(SearchBar);
A very concise answer would be:
mapStateToProps() is a utility which helps your component gets updated state(which is updated by some other components)
mapDispatchToProps() is a utility which will help your component to fire an action event (dispatching action which may cause a change of application state)
bindActionCreators() is mostly used when you want to pass some action creators down to a component that isn't aware of Redux, and you don't want to pass dispatch or the Redux store to it.
<Provider> makes the Redux store available to the your "connected" React components.
connect() is a higher-order component (HOC) that lets you inject Redux state into a regular React component.
Let's dive a bit deeper
ReactJS - JS library for building user interfaces.
Redux - JS library for managing application state.
Putting them together using react-redux:
If we want to link our React application with the Redux store, we first have to let our app know that this store exists. This is where we come to the first major part of the react-redux library, which is the Provider.
A Provider is a React component given to us by the react-redux library. It serves just one purpose: to “provide” the store to its child components.
Provider
Makes the Redux store available to the connect() calls in the component hierarchy below. Normally, you can’t use connect() without wrapping a parent or ancestor component in <Provider>. So ultimately connect does just that, it connects your React app to the Redux store.
//This is the store we create with redux's createStore method
const store = createStore(todoApp, {})
// Provider is given the store as a prop
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('app-node')
)
Props
store (Redux Store): The single Redux store in your application.
children (React Element): The root of your component hierarchy.
Explanation and usage of the Connect function:
Now that we have “provided” the redux store to our application, we can now connect our components to it. We established previously that there is no way to directly interact with the store. We can either retrieve data by obtaining its current state or change its state by dispatching an action (we only have access to the top and bottom component of the redux flow diagram shown previously). This is precisely what connect() does.
To use connect(), you need to define a special function called mapStateToProps that describes how to transform the current Redux store state into the props you want to pass to a presentational component you are wrapping.
In addition to reading the state, container components can dispatch actions. In a similar fashion, you can define a function called mapDispatchToProps() that receives the dispatch() method and returns callback props that you want to inject into the presentational component.
Simple explanation and a basic example of mapStateToProps
The Store is a box, which contains the entire application state. Imagine that this box is in an unknown location.
The components need to take some of the things out of the box but they only need some of the things stored in it. The components know what they need from the box but they don't know where the box is.
The mapStateToProps function is a filter used to select which things in the box are required by the component. The selected things become the component properties.
The mapStateToProps function is not enough because it selects the required things in the box but it doesn't know where the box is located.
The connect function knows where the box is located and passes it to the mapStateToProps function so it can grab what it needs.
Conclusion: mapStateToProps simply returns a specified part of the current state. mapStateToProps get the data that is fed to its component.
const mapStateToProps = (state) => {
return { things: state.things }
};
So now we're able to use that part of the state as props -> this.props.things
But what if the component wants to change the state? That is where mapDispatchToProps comes in.
Simple explanation and a basic example of mapDispatchToProps
As implied in its name, this function directs the dispatching or sending of an action by pointing it to an action creator. For example:
const mapDispatchToProps = () => {
return {
addThing: addThing,
doAnotherThing: doAnotherThing
}
}
mapDispatchToProps takes the dispatch functions in your component and executes them against the Redux reducer when that function is fired. Remember that Props aren’t just objects, they can also be functions. This is where mapDispatchtoProps applies. MapDispatchToProps allows for you to dispatch state changes to your store. An example would be a button click that triggers a refresh or an automatic loading of data once the component is mounted.
The action creator is made available to the component as a prop, which is usually tied to an event handler function contained in the component:
handleOnClick() {
this.props.addThing();
};
However, returning the action creator is only one part. We also want the send that returned action to the store. How do we do that? We use Redux’s bindActionCreators().
Simple explanation and a basic implementation of bindActionCreators():
Turns an object whose values are action creators, into an object with the same keys, but with every action creator wrapped into a dispatch call so they may be invoked directly.
Normally you should just call dispatch directly on your Store instance. If you use Redux with React, react-redux will provide you with the dispatch function so you can call it directly, too.
The only use case for bindActionCreators is when you want to pass some action creators down to a component that isn't aware of Redux, and you don't want to pass dispatch or the Redux store to it.
To implement it, we:
import { bindActionCreators } from 'redux';
...
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
addThing: addThing,
doAnotherThing: doAnotherThing
}, dispatch);
};
The bindActionCreators() function accepts the action creator and the store’s dispatch function as arguments, and returns a dispatch function that uses the return value of the action creator as its arguments.
Once again, tying this all together is the connect() function, in which we pass mapDispatchToProps as a second argument. For example:
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
which will export a component that can both get the current state from the store, and dispatch an action to the store to trigger and update to the state.
Now, let's put it all together with a little TodoItem.js React functional component:
import { connect } from 'react-redux'
const TodoItem = ({ todo, destroyTodo }) => {
return (
<div>
{todo.text}
<span onClick={destroyTodo}> x </span>
</div>
)
}
const mapStateToProps = state => {
return {
todo: state.todos[0]
}
}
const mapDispatchToProps = dispatch => {
return {
destroyTodo: () =>
dispatch({
type: 'DESTROY_TODO'
})
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(TodoItem)
mapStateToProps and mapDispatchToProps are both pure functions that are provided the stores “state” and “dispatch” respectively. Furthermore, both functions have to return an object, whose keys will then be passed on as the props of the component they are connected to.
In this case, mapStateToProps returns an object with only one key: “todo”, and mapDispatchToProps returns an object with the destroyTodo key.
The exported connected component provides todo and destroyTodo as props to TodoItem functional component

converting react classes to functions with redux

I'm still new to react/redux, after getting something like this to function
User.js
class User extends React.Component {
componentWillMount() {
this.props.fetchUser(.....);
}
render() {
return (
<Profile />
)
}
export default connect(null, {fetchUser})(User);
Profile.js
class Profile extends React.Component {
render() {
const { user } = this.props
return (
<h1>{user.profile.name}</h1>
)
}
const mapStateToProps = state => ({
user: state.store.user
});
export default connect(mapStateToProps, {})(Profile)
actions.js
export const fetchUser = (.....) => dispatch => {
fetch()
.....
}
reducers.js
case FETCH_USER:
return {
...state,
user: action.payload.user
};
As I understand it, the User component calls an action (fetchUser) from connect on componentWillMount(). That action calls an api, gets the data and the reducer adds that to the store within the state. The Profile component can then use connect to map the data from fetchUser in the store and display that data.
After reading some tutorials including https://github.com/reactjs/redux/blob/master/docs/basics/UsageWithReact.md
It looks like things can be simplified a bit without using classes.
If I were to change the User and Profile components to a more functional way, how would I do it?
eg.
const User = () => {
return (
<Profile />
)
}
how do I dispatch the fetchUser action and how do I simulate it to be called with the flow of componentWillMount()?
or am I just over complicating things?
There is also a way to support lifecycle methods in functional components.
https://www.npmjs.com/package/react-pure-lifecycle
import React from 'react';
import lifecycle from 'react-pure-lifecycle';
// create your lifecycle methods
const componentDidMount = (props) => {
console.log('I mounted! Here are my props: ', props);
};
// make them properties on a standard object
const methods = {
componentDidMount
};
const FunctionalComponent = ({children}) => {
return (
<div>
{children}
</div>
);
};
// decorate the component
export default lifecycle(methods)(FunctionalComponent);
I think you should keep using statefull components with redux...
https://medium.com/#antonkorzunov/2-things-about-purecomponent-you-probable-should-know-b04844a90d4
Redux connect — is a PureComponent.
Yes — a very important thing, a HoC for a molecule is a pure one. And works even inside other pure components. And gets store from a current context.
Same is working, for example, for styled-component — you can wrap it with PureComponent, but it will still react to Theme changes.
Solution is simple — bypass logic, use old school events bus, subcribe, wait and emit events.
Styled-componets:
componentWillMount() {
// subscribe to the event emitter. This
// is necessary due to pure components blocking
// context updates, this circumvents
// that by updating when an event is emitted.
const subscribe = this.context[CHANNEL];
this.unsubscribe = subscribe(nextTheme => { <----- MAGIC
React-redux:
trySubscribe() {
if (shouldSubscribe && !this.unsubscribe) {
this.unsubscribe =
this.store.subscribe(this.handleChange); <----- MAGIC
}
}
componentDidMount() {
this.trySubscribe();
}
Thus, even if parent Pure Component will block any update enables you to catch a change, store update, context variable change, or everything else.
So — something inside pure components is very soiled and absolutely impure. It is driven by side effects!
But this bypass straight logic flow, and works just differently from the rest of application.
So — just be careful. And don’t forget about magic.
Aaaand….
And this is a reason, why any redux store update will cause redraw in each connected component, and why you should use reselect just next to connect HoC —
to stop unnecessary change propagation.
But you should read this from another point of view:
redux-connect is a source of a change propagation.
redux connect is the end of a change propagation. It is still PureComponent.
And this leads to quite handy thing — you can control change propagation with redux-connect only. Just create a boundaries for a change. Lets talk about this in another article.
Conclusion
Pure components keep your application fast. Sometimes — more predictable, but often — less predictable, as long they change the way application works.
Stateless components are not pure, and may run slower than PureComponents by any kind.
But… if you very wish to create a fast application with good user experience — you have to use Pure Component.
No choice. But, now — you know hidden truth, and knew some magic…
React recommends that ajax request be made in componentDidMount(), rather than in componentWillMount(). For more info on this, read this post.
Since you want to make ajax requests in componentDidMount(), you need a class. There are two ways of writing component definitions: functional component and the class component. Functional components are more concise, but you don't get component lifecycle methods like componentDidMount(). Think of it as just a render function that takes props as inputs and outputs DOMs (in JSX). To override those lifecycle methods, you need to define them as a class.
If you want to use Redux, and want to make ajax requests in a Redux action, you should import the action creator function (fetchUser(..) in your case) that makes the ajax request, and dispatch(fetchUser(..)) in componentDidMount(). connect(..)ed components get dispatch(..) function passed to it by Redux store.
If you want to see how it's done in other redux apps, see the official example apps in the redux.js repo, paying attention to actions and containers: https://github.com/reactjs/redux/tree/master/examples
In Your case you can continue with statefull components no wrong in that
,If you need to go with functional way
There is a work arround
https://github.com/mobxjs/mobx/issues/162
Suggestion
Calling the api in componentDidMount will make sense than
componentWillMount , Because you can show the user something is
fetching.
I think,User component is designed nicely.It will act as a container for Profile to provide the Data.
Instead of making Profile component class oriented,it should be Stateless.
Lets User component pass the required data for Profile component.
You don't need to connect Profile component using redux-connect.Just render it as a Child component of User.
Profile
const Profile = (props) => {
const {user, likeProfile} = props;
//likeProfile()//call like this using dom event or programmatically.
return (
<h1>{user.profile.name}</h1>
)
}
You need to make some changes in User component.
Get the state for Profile component via mapStateToProps.
class User extends React.Component {
componentWillMount() {
this.props.fetchUser(.....);
}
render() {
const {user, likeProfile} = this.props;
return (
<Profile user= {user} likeProfile={likeProfile} /> //passed the user data to Profile component vua User
)
}
Map the user state for Profile in User connect.
const mapStateToProps = (state)=>{
return{
user : state.somereducerkey.user //this will be accessible in Profile via props { user}
}
}
export default connect(mapStateToProps, {fetchUser, likeProfile})(User);

How is this dispatch function coming from props?

I'm trying to learn from reading this app's code, and I am confused how you get dispatch from the props in this line of code:
_handleSubmit(e) {
e.preventDefault();
const { email, password } = this.refs;
const { dispatch } = this.props;
dispatch(Actions.signIn(email.value, password.value));
}
https://github.com/bigardone/phoenix-trello/blob/master/web/static/js/views/sessions/new.js#L17
Hoping someone can explain how calling this.props will return a dispatch?
react-redux is a library that helps components get values from the Redux store in a predictable and performant way. The main tool it provides is a function called connect, which wraps Redux components providing them with store values as props. The key part of the code you link to is at the bottom: https://github.com/bigardone/phoenix-trello/blob/master/web/static/js/views/sessions/new.js#L70-L74.
Say you have a value in the Redux store named counter. You want your component CounterDisplay to know about this value, and update when it changes:
class CounterDisplay extends Component {
render () {
const { counter, dispatch } = this.props
return (
<div>{counter}</div>
)
}
}
Those variables are going to be undefined unless you've explicitly put the values into props the 'old fashioned way':
<CounterDisplay counter={1} dispatch={() => {}} />
That's where connect comes in. It knows about the Redux store (often using another component called Provider) and can place values from it into the props of the component it's wrapping. It returns what's called a Higher Order Component (HOC): one that wraps another to perform a specific function, in this case connection to the store.
Here's how we'd get the counter value into props:
function mapStateToProps (state) {
// Slightly confusingly, here `state` means the entire application
// state being tracked by Redux... *not* CounterDisplay's state
return {
counter: state.counter
}
}
export default connect(mapStateToProps)(CounterDisplay)
So instead of exporting CounterDisplay itself, we export the HOC. In addition to counter, connect will also automatically insert the dispatch function into props so we can make use of it in the component. That's the behaviour you're seeing in the source you're reviewing.
const { dispatch } = this.props; is just deconstructing this.props.dispatch into a dispatch variable so it's used from props and where do they come to props? From react-redux connect:
export default connect(mapStateToProps)(SessionsNew);
connect is just Higher Order Component which basically connects your component with the store. As part of this process it puts dispatch into component's props
Edit:
The main idea is that connect is a function that takes whatever components and extends it's props with dispatch property (it returns another react components that wraps your component). You can also map some properties from state to your component and bind actions with dispatch using mapDispatchToProps and mapStateToProps
Just an example of destructuring assignment. See more here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Dispatch in react redux

I am new to react and redux xo my questions will sound basic.
What does dispatch means? I am referring to the term dispatching an action.
Why do we need mapDispatchToProps to store actions on redux? We can simply import an action and use it. I have a scenario in which I have to load data when a component is mounted.
#mariazahid mapDispatchToProps will bind the action to your component so that you can pass it down to your presentation components. This is a pattern that is normally used within using Redux with React.
You can import your action and just dispatch the action, but in most scenarios a container -> component pattern is used. A container is where the actions are mapped to and the state and the only goal of this component is to pass this data down to components that are used for presenting that data.
When working in teams, it's a pattern that is easily adoptable. Instead of importing actions from left right and center, you will just have to be aware of the container and how it passes the required actions/data down to the children.
From an implementation perspective, dispatch is just a method that is used to communicate with your reducers
Let say that your action looks something like this
function myAction() {
return { type: 'MY_ACTION' };
}
You're trying to communicate with the reducer that responds to the action type 'MY_ACTION'
In your mapDispatchToProps you'd typically do something like this;
function mapDispatchToProps(dispatch) {
return { actions: bindActionCreators(myActions, dispatch) }
}
Effectively, you're wrapping(binding) your actions to the dispatch method;
function bindActionCreators(actions, dispatch) {
// this is a very trivial implementation of what bindActionCreators does
let wrappedActions = {};
Object.keys(actions).forEach(action =>
// for every action, return a function that calls dispatch on the result of what your action returns
return function(...args) {
// remember here that dispatch is the only way you can communicate with the reducers and you're action's type will determine which reducer responds to return the new state
return dispatch(actions[action](..args));
}
);
}
And so, these "bound" actions are now assigned to a props.actions in your component.

Confused about an auth0 lock example using react and redux

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

Resources