Categories
Redux

Intro to React State Management with React-Redux

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

To store data in a central place for easy accessibility by components, we have to use some state management solutions. React-Redux is a popular choice.

In this article, we’ll look at how to add it to our React app and simple use cases.

Installation

To install the react-redux package, we have install react-redux and its dependency redux .

We can install both by running:

npm install react-redux redux

with NPM or if we use Yarn:

yarn add react-redux redux

Set Up a Redux Store

After installing both packages, we have to set up our Redux store to hold our data.

To do this we write:

import { createStore } from "redux";

function counterReducer(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    default:
      return state;
  }
}

const store = createStore(counterReducer);

The code above creates a Redux store by creating the counterReducer reducer function.

The reducer specifies how the app’s state changes in response to actions sent to the store.

Our counterReducer only accepts one action, which is 'INCREMENT' . We respond to the action by returning the state and adding 1 to it.

There’s also a default case to just return the state value as is.

Then we create a store by calling Redux’s createStore function and passing in our reducer.

It returns the store , which we can pass into our React app.

Connecting the Store to our React App

This is where we need the functions of React-Redux.

We can connect the store to our app so we can store our app’s state in the store by using React-Redux’s connect function.

connect takes 2 functions, which are mapStateToProps and mapDispatchToProps . They’re the first and second argument respectively.

First, we can put the whole app together by connecting our store with the React app as follows:

import React from "react";
import { Provider, connect } from "react-redux";
import { createStore } from "redux";
import ReactDOM from "react-dom";

function counterReducer(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    default:
      return state;
  }
}

const store = createStore(counterReducer);

class App extends React.Component {
  onClick() {
    this.props.increment();
  }
  render() {
    const { count } = this.props;
    return (
      <>
        <button onClick={this.onClick.bind(this)}>Increment</button>
        <p>{count}</p>
      </>
    );
  }
}

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch({ type: "INCREMENT" })
  };
};
const mapStateToProps = state => ({
  count: state
});

App = connect(
  mapStateToProps,
  mapDispatchToProps
)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);

In the code, we have an app that shows a number going up as we click the Increment button.

The first step to connect the store to our React app is to wrap the Provider component around our whole app.

To do this we, wrote the following:

<Provider store={store}>
  <App />
</Provider>

Then we define the mapStateToProps and mapDispatchToProps functions as follows:

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch({ type: "INCREMENT" })
  };
};
const mapStateToProps = state => ({
  count: state
});

In mapStateToProps we return a object to map the state object to a React component prop name as indicated in the property name. The state is the state stored in the Redux store.

So we mapped state to the prop count .

In mapDispatchToProps , we get the dispatch parameter, which is a function used to dispatch our action to the store, and return an object with the name for the function we can access from the props to call and dispatch the action.

So in mapDispatchToProps , increment is our function name. We can call it by running this.props.increment in our App component.

increment is a function that runs dispatch({ type: “INCREMENT” }) .

Then in our App component, we define the onClick method to call this.props.increment to dispatch the ‘INCREMENT’ action to our counterReducer via our Redux store and increase the state by 1.

Then since we have mapStateToProps , the latest value is being observed by App and the latest value is available via this.state.count as indicated in mapStateToProps .

Then when we click the Increment button, we’ll get the number going up by 1.

This will happen with every click.

Conclusion

We can use Redux in our React app by creating a store.

Next, we use the React-Redux Provider component and wrap it around our App entry-point component. We pass our Redux store to the store prop so that we can map the state and dispatch actions to props.

Then connecting it to our store via React Redux’s connect function. We pass in the mapStateToProps and mapDispatchToProps to map the store’s state to our component’s props and map our dispatch function call to our props respectively.

Categories
Redux

Using the React-Redux useSelector Hook

With Redux, we can use it to store data in a central location in our JavaScript app. It can work alone and it’s also a popular state management solution for React apps when combined with React-Redux.

In this article, we’ll look at the new hooks React-Redux Hooks API.

Using the useSelector Hook in a React Redux App

The hooks API consists of the useSelector , useDispatch , and useStore hooks.

The useSelector hook takes a selector function to select data from the store and another function equalityFn to compare them before returning the results and determine when to render if the data from the previous and current state are different.

The call takes the following format:

const result : any = useSelector(selector : Function, equalityFn? : Function)

It’s equivalent to mapStateToProps in connect. The selector will be called with the entire Redux store state as its only argument.

The selector function may return any value as a result, not just an object. The return value of the selector will be used as the return value of the useSelector hook.

When an action is dispatched, useSelector will do a shallow comparison of the previous selector result value and the current one.

The selector function doesn’t receive an ownProps argument. Props can be used through closure or by using the curried selector.

We may call useSelector multiple times within a single function component. Each call creates an individual subscription to the Redux store. React update batching behavior will cause multiple useSelector s in the same component to return new value should only return in a single re-render.

Equality Comparisons and Updates

The provided selector function will be called and its result will be returned from the useSelector hook. A cached result may be returned if the selector is run and returns the same result.

useSelector only forces a re-render if the selector result appears to be different than the last result.

This is different from connect , which uses shallow equality checks on the results of mapState calls to determine if re-rendering is needed.

If we want to retrieve multiple values from the store, we can call useSelector multiple times with each call returning a single field value, use Reselect or a similar library to create a memoized selector that returns multiple values in an object but returns a new object when one of the values is changed.

We can also use the shallowEqual function from React-Redux as the equalityFn argument to useSelector .

For example, we can use useSelector as follows:

import React from "react";
import ReactDOM from "react-dom";
import { Provider, useSelector, useDispatch } from "react-redux";
import { createStore } from "redux";
function count(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}

const store = createStore(count);

function App() {
  const count = useSelector(state => state);
  const dispatch = useDispatch();

  return (
    <div className="App">
      <button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
      <button onClick={() => dispatch({ type: "DECREMENT" })}>Decrement</button>
      <p>{count}</p>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);

In the code above, we created the store as usual. Then in the App component, we used the useSelector hook to get the count by passing in the state => state function.

Then we get the dispatch function to useDispatch .

We can use the second argument of the useSelect hook as follows:

import React from "react";
import ReactDOM from "react-dom";
import { Provider, useSelector, useDispatch, shallowEqual } from "react-redux";
import { createStore } from "redux";
function count(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}
const store = createStore(count);
function App() {
  const count = useSelector(state => state, shallowEqual);
  const dispatch = useDispatch();
  return (
    <div className="App">
      <button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
      <button onClick={() => dispatch({ type: "DECREMENT" })}>Decrement</button>
      <p>{count}</p>
    </div>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);

React-Redux has a shallowEqual function to compare data to determine when to update data. We can also define our own function to compare the previous and current state to determine updates.

Conclusion

We can use the useSelector hook to get the data from the Redux store in a React component.

It takes 2 arguments. The first argument is a function that returns the state, and the second argument is a function that checks if the previous and current state are equal to determine when to update.

Categories
Redux

Accessing the Store with React-Redux

With Redux, we can use it to store data in a central location in our JavaScript app. It can work alone and it’s also a popular state management solution for React apps when combined with React-Redux.

In this article, we’ll look at how to access the Redux store with React-Redux.

Accessing the Store

With React-Redux, we can access the store by defining a mapStateToProps function.

However, we can also access it in a customized way. Internally, React-Redux uses React’s Context API to make the Redux store accessible to deeply nested connected components.

Currently, React-Redux is normally handled by a single default context object instance generated by React.createContext() called ReactReduxContext .

Provider uses ReactReduxContext.Provider to put the Redux Store and the current state into context and connect uses ReactReduxContext.Consumer to read values and handle updates.

Providing Custom Context

We can provide a custom context to React-Redux via the context prop.

For example, we can pass in our own context in the following code:

import React from "re
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore } from "redux";
function count(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}
const store = createStore(count);

function App({ increment, decrement, count }) {
  return (
    <div className="App">
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <p>{count}</p>
    </div>
  );
}
const mapStateToProps = state => {
  return { count: state };
};
const increment = () => ({ type: "INCREMENT" });
const decrement = () => ({ type: "DECREMENT" });
const customContext = React.createContext();

App = connect(
  mapStateToProps,
  { increment, decrement },
  null,
  { context: customContext }
)(App);

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store} context={customContext}>
    <App />
  </Provider>,
  rootElement
);

In the code above, we have the usual React-Redux code for connecting the store to the App component via connect .

However, we create a customContext via:

const customContext = React.createContext();

Then in the connect call, we have:

App = connect(
  mapStateToProps,
  { increment, decrement },
  null,
  { context: customContext }
)(App);

The 4th argument is { context: customContext } , which is where we set our custom context.

Also, we have:

<Provider store={store} context={customContext}>
  <App />
</Provider>

to set our context prop via context={customContext} .

Multiple Stores

We can also use multiple stores with React-Redux by nesting providers as follows:

import React from "react";
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore, compose } from "redux";
function countA(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    default:
      return state;
  }
}

function countB(state = 0, action) {
  switch (action.type) {
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}

const storeA = createStore(countA);
const storeB = createStore(countB);
function App({ increment, decrement, countA, countB }) {
  return (
    <div className="App">
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <p>{countA}</p>
      <p>{countB}</p>
    </div>
  );
}
const mapStateToPropsA = state => {
  return { countA: state };
};

const mapStateToPropsB = state => {
  return { countB: state };
};

const increment = () => ({ type: "INCREMENT" });
const decrement = () => ({ type: "DECREMENT" });
const contextA = React.createContext();
const contextB = React.createContext();

App = compose(
  connect(
    mapStateToPropsA,
    { increment },
    null,
    { context: contextA }
  ),
  connect(
    mapStateToPropsB,
    { decrement },
    null,
    { context: contextB }
  )
)(App);

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={storeA} context={contextA}>
    <Provider store={storeB} context={contextB}>
      <App />
    </Provider>
  </Provider>,
  rootElement
);

In the code above, we defined 2 separate stores by writing:

const storeA = createStore(countA);
const storeB = createStore(countB);

where countA and countB are the reducers.

Then we nest our connect calls within the arguments of the compose function to combine the connects as follows:

App = compose(
  connect(
    mapStateToPropsA,
    { increment },
    null,
    { context: contextA }
  ),
  connect(
    mapStateToPropsB,
    { decrement },
    null,
    { context: contextB }
  )
)(App);

We defined mapStateToPropsA and mapStateToPropsB to map states from the 2 stores before this call.

Then in the last argument of each connect , we pass in an object with the context that we want to use to connect the store to App .

Then in the ReactDOM.render call, we pass in:

<Provider store={storeA} context={contextA}>
  <Provider store={storeB} context={contextB}>
    <App />
  </Provider>
</Provider>

to set the store and context we want to use for each provider. The context prop of each Provider have to match with connect .

Conclusion

We can access multiple stores by nesting multiple Providers and providing a store and context for each.

The context is defined by calling React.createContext() , which is part of the React Context API used to share data between components.

Then we can use the compose function to add combine multiple connect calls together. We pass into the 4th argument of connect in each call.

We can also use the same method to customize access to a single store, except that we don’t need to call compose .

Categories
Redux

Defining and Using React Redux mapDispatchToProps

With Redux, we can use it to store data in a central location in our JavaScript app. It can work alone and it’s also a popular state management solution for React apps when combined with React-Redux.

In this article, we’ll look at how to define and use the mapDispatchToProps function to map dispatch to props so we can call them in our React components.

Approaches for Dispatching

dispatch is a function of the Redux store. We call the store.dispatch method to dispatch an action to the tore.

It’s the only way to trigger a state change.

React components never access the store directly. We use the connect function to do it.

React Redux gives us 2 ways to let our components dispatch actions. We can either receive dispatch as a prop to dispatch actions itself, or we can use the connect function with a mapDispatchToProps function and pass as props to our component.

Default: dispatch as a Prop

For example, if we have the following code:

import React from "react";
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore } from "redux";

function message(state = "", action) {
  switch (action.type) {
    case "SET_MESSAGE":
      return action.message;
    default:
      return state;
  }
}

const store = createStore(message);

const mapStateToProps = (state, ownProps) => {
  const { color } = ownProps;
  return { color, message: state };
};

function App({ dispatch, message }) {
  const onClick = () => {
    if (message === "bar") {
      dispatch({ type: "SET_MESSAGE", message: "foo" });
    } else {
      dispatch({ type: "SET_MESSAGE", message: "bar" });
    }
  };
  return (
    <div className="App">
      <button onClick={onClick}>Click Me</button>
      <p>{message}</p>
    </div>
  );
}

App = connect(mapStateToProps)(App);

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);

Then when we click the button, we toggle between ‘foo’ and ‘bar’ being displayed because the connect higher-order component gives us the dispatch prop, which we can use to dispatch actions to our store.

Providing a mapDispatchToProps Parameter

The second way to use the mapDispatchToProps function to map the dispatch functions to our React component as props.

This is useful because we don’t have to call dispatch with all the arguments all the time.

It makes the dispatch implementation more declarative. With mapDispatchToProps , our component code doesn’t need to be aware of dispatch anymore.

mapStateToProps encapsulates the logic of talking to the Redux store so we don’t have to worry about it.

Two Forms of mapDispatchToProps

mapStateToProps can take the form of a function or an object. The function version allows for more customization since it as access to dispatch and ownProps as an option.

The object shorthand is shorter and easier to use. It’s better to use the object unless we have to customize dispatching in some way.

We’ll look at how to define mapDispatchToProps as a function.

Photo by Stephanie Studer on Unsplash

Defining mapDispatchToProps As A Function

We can define mapDispatchToProps as a function by defining a function that takes dispatch and optionally ownProps and calling dispatch with some action in the function.

We can use mapDispatchToProps as follows:

import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore } from "redux";

function messages(state = 0, action) {
  const words = ["foo", "bar", "baz"];
  switch (action.type) {
    case "GET_BY_INDEX":
      return words[action.index];
    default:
      return state;
  }
}

const store = createStore(messages);

function Message({ getByIndex, index, message }) {
  useEffect(() => {
    getByIndex(index);
  }, []);
  return (
    <div className="App">
      <p>{message}</p>
    </div>
  );
}

const mapStateToProps = (state, ownProps) => {
  return { message: state };
};

const mapDispatchToProps = (dispatch, ownProps) => {
  const { index } = ownProps;
  return {
    getByIndex: index => dispatch({ type: "GET_BY_INDEX", index })
  };
};

Message = connect(
  mapStateToProps,
  mapDispatchToProps
)(Message);

function App() {
  return (
    <div className="App">
      <Message index={0} />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);

In the code above, we have the store which lets us get messages from a list of words from the words array.

Then we defined mapDispatchToProps as follows:

const mapDispatchToProps = (dispatch, ownProps) => {
  const { index } = ownProps;
  return {
    getByIndex: index => dispatch({ type: "GET_BY_INDEX", index })
  };
};

In the code above, we have ownProps to access the index prop that we passed to the Message component.

Then we returned an object with the getByIndex method which takes an array index then we call dispatch with action type 'GET_BY_INDEX' and the index property with the index parameter as the value.

In the Message component, we get the getByIndex function that we returned from mapDispatchToProps , and index prop, and the message prop that we got from mapStateToProps and we used all of them.

We called getByIndex with the index prop value to get the string from the store with the given index in the useEffect callback. Then we displayed what we retrieved by adding:

<p>{message}</p>

Note that each field that returned in the object of mapStateTiProps will become a separate prop for our own component.

They’ll be merged with existing props.

Conclusion

To map code for dispatching actions to our React components, we can define the mapDispatchToProps function, which takes the dispatch function and ownProps as arguments. dispatch is what we call to dispatch actions to the store, and ownProps is an object with the props that we passed into components.

For dispatching simple actions, we can just use the connect function without defining a mapDispatchToProps function and we can call props.dispatch directly in the component to dispatch store actions since the connect higher-order component passed that to our component.

Categories
Redux

Defining and Using React Redux mapStateToProps Function

With Redux, we can use it to store data in a central location in our JavaScript app. It can work alone and it’s also a popular state management solution for React apps when combined with React-Redux.

In this article, we’ll look at how to use mapStateToProps to subscribe to the store’s state and them to a React component’s props.

mapStateToProps Definition

The React Redux’s mapStateToProps has 2 parameters. The first is the state and the second is an optional ownProps parameter.

It returns a plain object containing the data that the connected component needs.

It doesn’t matter if it’s a traditional function or an arrow function. Both kinds will give the same result.

The first argument, which is state , has the entire Redux store state. It’s the same value returned by store.getState() .

It’s usually called state . However, we can call it whatever we want.

The second parameter, ownProps , is an optional parameter that has the props of a component.

In the following example:

import React from "react";
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore } from "redux";

function message(state = "hello", action) { switch (action.type) { default: return state; } }

const store = createStore(message);

function Message({ color, message }) { return <div style={{ color }}>{message}</div>; }

const mapStateToProps = (state, ownProps) => {
  const { color } = ownProps;
  return { color, message: state };
};

Message = connect(mapStateToProps)(Message);

function App() {
  return (
    <div className="App">
      <Message color="blue" />
    </div>
  );
}

const rootElement = document.getElementById("root"); ReactDOM.render( <Provider store={store}> <App /> </Provider>, rootElement );


`ownProps` would have the value of the `color` prop because that’s what we passed in.

In this case, that should be`blue` .

From the `mapStateToProps` function, we should also get the state from the store. In this case, we get the `'hello'` string returned from the `message` reducer function. So we should see ‘hello’ in the browser screen.

`mapStateToProps` function should be pure and synchronous. It only take the `state` and `ownProps` and return something that’s derived from it by running synchronous code.

This means no asynchronous HTTP calls, `setTimeout` , async functions, etc.

### Return Values Determine If Your Component Re-Renders

React-Redux internally implements the `shouldComponentUpdate` method. Therefore, the `Provider` will re-render when the data of our component has changed.

Data also includes entities retrieved from `mapStateToProps` .

The comparison is done by using the `===` comparison on each field of the returned object.

`mapStateToProps` runs when the store `state` changes. Or when `state` changes or `ownProps` is different if both `state` and `ownProps` are referenced.

The component re-renders when any field that’s returned by `mapStateToProps` is different.

If both `state` and `ownProps` are referenced in `mapStateToProps` , the component re-renders when any field of `stateProps` or `ownProps` are different.

### Only Return New Object References If Needed

Because `mapStateToProps` and re-rendering is done when we return new object or array references, we should only return new objects when we need them.

Therefore, we should avoid any code that returns new objects, like `array.map()` , `array.filter()` , etc.

If we need to run code that returns new object references, then they should be memoized so that they don’t trigger re-render even if their content is the same.

![](https://cdn-images-1.medium.com/max/800/0*MyfaaQ74D5h-plLE)Photo by [Pineapple Supply Co.](https://unsplash.com/@pineapple?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

### `mapStateToProps` Will Not Run if the Store State is the Same

Every time an action is dispatched, `store.getState()` is called to check if the previous state and the current state are the same.

If both states are identical by reference, then `mapStateToProps` won’t be run again since it assumes that the rest of the store haven’t changed.

`combineReducers` returns the old state object instead of the new one if there’re no changes in the store’s state.

### The Number of Declared Arguments Affects Behavior

If `ownProps` is omitted from the parameters, then `ownProps` won’t be retrieved. Therefore, we should only add `ownProps` to the parameter is we need it.

For example, if we have the following `mapStateToProps` function:

function mapStateToProps(state) { console.log(state) console.log(arguments[1]) }


The `arguments[1]` is `undefined` since we didn’t include the `ownProps` parameter.

### Conclusion

We can define `mapStateToProps` and use it to get the latest state from our Redux Store to our React app via the `connect` function.

It has 2 parameters, which are `state` for the store’s state and `ownProps` for the props that we pass into the component ourselves.

The `connect` function lets us pass in `mapStateToProps` as the first argument and returns a function where we can pass in our component into the it and returns a new component that subscribes to the store’s state and gets it as props.