React Redux is maintained by the Redux team, and kept up-to-date with the latest APIs from Redux and React.

React is all about moving parts that pass information to each other. You will notice sometimes you have really long chains that go through several containers and several components. This can be a hassle if the data got messed up in one of the steps and you have to slowly backtrack and look through each part to find the error. there is where Redux comes into play! Redux stores all of your state information in a separate object, and any component can get the information it needs from this object. So instead of going home => container1 => component1=> component2, it will go home => Redux Object => component2. Lets see how this all works!

First is the reducer function.

You have two objects that are separate from everything else, the state and the action. The state contains, well, the state of your page, and the action contains the instructions to update that state.

let state = {name: "abc"}
let action = {type: "JOE-IFY"}

To allow action to modify state, you need a function.

function changeState(state, action) {
   if (action.type === 'JOE-IFY') {
      return {name: 'Joe'}
   }
}

If the action type is ‘JOE-IFY’, change the state of name to be “Joe”. There can be many different commands to change names, typically a switch case it used. However, to make sure a null or undefined is never returned a default case is added that returns the previous state.

function changeState(state, action) {
   switch (action.type) {
      case 'JOE-IFY':
         return {name: 'Joe'}
      default: 
         return: state
   }
}

Now if you ran the changeState function with the state and “JOE-IFY” you would get {name: “Joe”}.

If you had another action type, for example to change the name to “Bob” it would look like:

function changeState(state, action) {
   switch (action.type) {
      case 'JOE-IFY':
         return {name: 'Joe'}
      case 'BOB-IFY':
         return {name: 'Bob'}
      default: 
         return: state
   }
}

Now if you instead ran it with the function “BOB-IFY” you would get {name: “Bob”}. This changeState function is called the “reducer”, as it reduces the state and action into a new state.

You can make it more complicated as well, since an action can have multiple attributes.

let state = {name: "abc"}
let action = {type: "CHANGE_NAME",
              newName: "Spooderman"}

You will have to change the function such that it changes the state of name to that of newName. Something like:

function changeState(state, action) {
   switch (action.type) {
      case 'CHANGE_NAME':
         return {name: action.newName}
      default: 
         return: state
   }
}

This is the gist of how a reducer function works.

Using Redux in a React App

First install redux.

npm install redux

Install react-redux.

npm install react-redux

Inside your “src” folder, create a “reducers” folder, and inside the “reducers” folder create a “reducerFunctionName.js” file.

Redux gives you the createStore() function, which when called returns the state. React-redux gives you the “provider” component, where store is passed in and is subsequently passed down everywhere else. React-redux also lets us re-render whenever the specified changes to the state happen via the connect method. Import them both into index.js. Also import your reducer function.

import {createStore} from 'redux';
import {Provider} from 'react-redux'
import reducerFunctionName from './reducers/reducerFunctionName.js'
const store = createStore(reducerFunctionName);
ReactDom.render(
   <Provider store={store}>
      {' '}
      <App />
   </Provider>, 
   document.getElementById('root')
)

Now we can pass the store and access it in every component. To any component that wishes to access the store, import connect from react-redux and modify the export.

import {connect} from 'react-redux'
const mapStateToProps = state => {
   return {
      name: state.name
   }
}
const mapDispatchToProps = state => {
   return {
      changeName: () => dispatch({type: "CHANGE_NAME"})
   }
}
export default connect(
   mapStateToProps,
   mapDispatchToProps
)(App);

mapDispatchToProps allows us to have access to the “changeName” function, which is what we are calling us passing in action.type “CHANGE_NAME” to the reducer. Similarly, name is provided by the mapStateToProps function, which gives us access to the name in the state.

Your components now have access to the state information inside the store object, and are able to access the functions needed to change the state. Just about done!

One final thing. Now what if you had multiple functions? You can theoretically transform all of them into different cases for the same reducer function, but this would be weird; you would have a case for “CHANGE_NAME”, a case for “BUY_FOOD”, and other cases for tons of weird things that have nothing to do with each other. It is better to separate out the reducer functions. This can be done through “combineReducers”.

In the “reducers” folder create a new file called “rootReducer.js”. At the top enter:

import {combineReducers} from 'redux'

Then copy paste your other reducer functions over, but without the export default part in front of them. Then add it to the end.

export default combinedReducers({
   nameChanger,
   colorChanger
})

Note that now to access information from on of the reducers you have to specify the reducer name first now, so instead of “state.name” if name is stored in the nameChanger function you need to do “state.nameChanger.name”.

Go back to your index.js and import rootReducer from “./reducers/rootReducer.js”, you don’t need the earlier individual file imports anymore.

Your finished combinedReducer should look something like this:

import {combineReducers} from 'redux'
function colorChanger(state = {color: "red"}, action) {
  switch (action.type) {
    case 'CHANGE_COLOR':
      console.log(state);
      return {color: action.newColor}
    default:
      return state;
  }
}
function nameChanger(state = {name: "zed"}, action) {
  switch (action.type) {
    case 'CHANGE_NAME':
      console.log(state);
      return {name: action.newName}
    default:
      return state;
  }
}
export default combineReducers({
  nameChanger,
  colorChanger
})

And an example app.js that uses the above reducers might look something like:

import './App.css';
import React, {Component} from 'react';
import {connect} from 'react-redux';
import Something from './containers/Something.js'
class App extends Component {
handleChange = (event) => {
    this.props.changeName(event.target.value)
  }
handleChange2 = (event) => {
    this.props.changeColor(event.target.value)
  }
render () {
    return (
      <div className="App">
        <form>
          <label>
          NewName: <input type="text" onChange={event => {this.handleChange(event)}}/>
          <br/>
          NewColor: <input type="text" onChange={event => {this.handleChange2(event)}}/>
          </label>
          <br/>
          <input type="submit"/>
        </form>
        <p>{this.props.name}</p>
        <p>{this.props.color}</p>
      </div>
    )
  }
}
const mapStateToProps = state => {
  return {
    name: state.nameChanger.name,
    color: state.colorChanger.color
  };
}
const mapDispatchToProps = dispatch => {
  return {
    changeName: (event) => dispatch({type: 'CHANGE_NAME', newName: event }),
    changeColor: (event) => dispatch({type: 'CHANGE_COLOR', newColor: event })
  };
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

The default states for name and color are shown at the bottom. The redux state for name and color can be updated through the input bars, and the updated state is shown again with the new name and color.

And we are all done! That was a long ride and took me quite a while to figure out, so hopefully this guide helps you learn Redux faster than I did! Happy coding with your newfound knowledge of Redux!

#reactjs #redux

Redux in React
16.00 GEEK