Skip to content

Instantly share code, notes, and snippets.

@simaodeveloper
Last active December 7, 2018 19:56
Show Gist options
  • Save simaodeveloper/93f32bf97f90897790006e034b2824a8 to your computer and use it in GitHub Desktop.
Save simaodeveloper/93f32bf97f90897790006e034b2824a8 to your computer and use it in GitHub Desktop.

My Tips to Learning React with Redux

How to use React with Redux

We need to use a react-redux package to accomplish this connection between Redux and React. The ReactRedux provides a small API with two key features: Provider and connect. The Provider is a wrapper component from ReactRedux that wraps your React app. This wrapper then allows you to access the Redux store and dispatch function throughout your component tree. Provider takes two props, the Redux store and the child components of your app.

const Provider = ReactRedux.Provider;

class Root extends React.Component {
  constructor(props) {
    super(props);
  }
  
  render() {
    return (
      <Provider store={ store }>
        <App />
      </Provider>
    )
  }
}

Map State to Props

The Provider component allows you to provide state and dispatch to your React components, but you must specify exactly what state and actions you want. This way, you make sure that each component only has access to the state it needs. You accomplish this by creating two functions mapStateToProps() and mapDispatchToProps().

In these functions, you declare what pieces of state you want to have access to and which action creators you need to be able to dispatch.

Note: Behind the scenes, React Redux uses the store.subscribe() method to implement mapStateToProps().

function mapStateToProps(state) {
    return {
        messages: state
    }
}

Map Dispatch to Props

The mapDispatchToProps() function is used to provide specific action creators to your React components so they can dispatch actions against the redux store. It returns an object that maps dispatch actions to property names, which become component props.

Therefore, each property returns a function taht calls dispatch because it's passed in to mapDispatchToProps() as a parameter when you define the function. Behind the scenes, React Redux is using Redux's store.dispatch() to conduct these dispatches with mapDispatchToProps().

Note: Behind the scenes, React Redux uses the store.subscribe() method to implement mapDispatchToProps().

const addMessage = (message) => {
  return {
    type: 'ADD',
    message: message
  }
};

// change code below this line
function mapDispatchToProps(dispatch) {
    return {
        submitNewMessage: function(message) {
            dispatch(addMessage(message));
        }
    }
}

Connect Redux to React

Now that you've written both the mapStateToProps() and the mapDispatchToProps() functions, you can use them to map state and dispatch to the props of one of your React components. The connect method from React Redux can handle this task. This method takes two optional arguments, mapStateToProps() and mapDispatchToProps().

They are optional because you may have a component that only needs access to state but doesn't need to dispatch any actions, or vice versa.

To use this method, pass in the functions as arguments, and immediately call the result with your component. This syntax is a little unusual and looks like:

connect(mapStateToProps, mapDispatchToProps)(MyComponent);

Note: if you want to omit one of the arguments to the connect method, you pass null in it's place.

const addMessage = (message) => {
  return {
    type: 'ADD',
    message: message
  }
};

const mapStateToProps = (state) => {
  return {
    messages: state
  }
};

function mapDispatchToProps(dispatch) {
    return {
        submitNewMessage: function(message) {
            dispatch(addMessage(message));
        }
    }
}

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <h3>This is a Presentational Component</h3>
  }
};

const connect = ReactRedux.connect;
const ConnectedComponent = connect(mapStateToProps, mapDispatchToProps)(MyComponent)

Connect Redux to the Messages App

const store = Redux.createStore(messageReducer);

const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;

const ContainerComponent = connect(
  mapStateToProps,
  mapDispatchToProps
)(AppComponent);

class RootComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  
  render() {
    return (
      <Provider store={store}>
        <ContainerComponent />
      <Provider />
    )
  }
}

Extract Local State into Redux

Now that Redux is connected, you need to extract the state management out of the MyComponent component and into Redux. Currently, you have Redux connected, but you are handling the state locally within the MyComponent component.

In the MyComponent component, first, remove the messages property in the local state.

before
this.state = {
  input: '',
  messages: [],
};
after
this.state = {
  input: '',
};

These messages will be managed by Redux. Next, modify the submitMessage() method so that it dispatches submitNewMessage() from this.props, and pass in the current message input from local state as an argument. Because you removed messages from local state, remove the messages property from the call to this.setState() here as well.

before
submitMessage() {
  const currentMessage = this.state.input;
  this.setState({
    input: '',
    messages: [...this.state.messages, currentMessage]
  });
}
after
submitMessage() {
  this.props.submitNewMessage(this.state.input);
  this.setState({
    input: ''
  });
}

Finally, modify, the render() method so that it maps over messages received from props rather than state.

before
render() {
  return (
    <div>
      <ul>
        { this.state.messages.map((message, idx) => <li key={idx}>{message}</li>) }
      </ul>
    </div>
  );
}
after
render() {
  return (
    <div>
      <ul>
        { this.props.messages.map((message, idx) => <li key={idx}>{message}</li>) }
      </ul>
    </div>
  );
}

Moving Forward From Here

setup React and Redux

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider, connect } from 'react-redux';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

import rootReducer from './redux/reducers';
import App from './components/App';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

ReactDOM.render(
  <Provider store={ store}>
    <App />
  <Provider />,
  document.getElementById('root')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment