Mattermost Logo
Edit on GitHub

Using Redux with React

Using Redux with React is fairly straightforward thanks to the React Redux library. It provides the connect function to create higher order components that have access to the Redux store to set their props.

A typical Redux-connected component will be in its own folder with two files: index.jsx containing the code to connect to the Redux store and the file where the component is actually implemented. This helps to keep the Redux logic separate from the rendering for the component which keeps it more easily readable and makes it easier to test since it can be done without the whole Redux store.

// components/my_component/index.jsx

import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';

import {messageUser} from 'actions/entities/users';

import {getCurrentUser, getUser} from 'selectors/entities/users';

import MyComponent from './my_component';

// mapStateToProps receives the Redux store state and any props passed into the connected
// component, and they are used to return any additional data from the Redux store that is
// needed to render the component. ownProps will also be passed directly to the component.
function mapStateToProps(state, ownProps) {
    return {
        currentUser: getCurrentUser(state),
        otherUser: getUser(state, ownProps.userId)
    };
}

// mapDispatchToProps receives the Redux store's dispatch method so that bindActionCreators
// can be used to automatically dispatch those actions as necessary.
function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators({
            messageUser
        }, dispatch)
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);

// components/my_component/my_component.jsx

import React from 'react';

export default class MyComponent extends React.PureComponent {
    handleClick = () => {
        this.props.actions.messageUser(otherUser, currentUser, `Hello, ${this.props.otherUser.first_name}!`);
    };

    render() {
        return (
            <label>
                {`${this.props.otherUser.first_name} ${this.props.otherUser.last_name}: `}
                <button onClick={this.handleClick}>{'Say Hi'}</button>
            </label>
        );
    }
}

Both mapStateToProps and mapDispatchToProps are optional and can be omitted as necessary.

If you’re using a selector that is produced through a factory, such as makeGetUser, you can instead generate an individual mapStateToProps function for each instance of the component.

// component/my_component/index.jsx

...

import {getCurrentUser, makeGetUser} from 'selectors/entities/users';

// makeMapStateToProps is called once for each instance of the component on the page. Because of this
// a separate getUser selector is created for each instance, allowing them to be memoized separately.
function makeMapStateToProps() {
    const getUser = makeGetUser();

    return (state, ownProps) => {
        return {
            currentUser: getCurrentUser(state),
            otherUser: getUser(state, ownProps.userId)
        };
    };
}

...

export default connect(makeMapStateToProps, mapDispatchToProps)(MyComponent);

Performance Considerations 

Something very important to note when using React with Redux is that every single mapStateToProps function within your application will be called whenever anything in the store changes. If any work being done in mapStateToProps performs any complicated calculations or returns rich objects, it should be moved into a selector so that it can be memoized whenever possible.