Redux

Intro to Redux

Redux is a Predictable State Container for JavaScript Apps, its not just for React. In order to utilize it with React we utilize both the Redux library and the React-Redux library. Now below is an example of the most bare bones react app using Redux and React-Redux I could create. It has a single piece of state managed by Redux which is just a string saying either "yes" or "no" changed by clicking one of two buttons. I've kept the logic as simple as possible so there's minimal clutter and we can more easily track whats happening Redux and React-Redux. We will review each of the four files that makes up example individually, but if you would like to see the app as a whole and keep it on your machine for future reference you can download it from my Github here.Basic Redux App Github

Press the Buttons Below To Sign In or Sign Out

Are you signed in?: no

index.js

The first file we’re going to look at is the root index.js. The first thing to note is the import statements
import { createStore } from "redux";
import { Provider } from "react-redux";
import reducers from "./reducers";
The Reduxstoreis created by using thecreateStorefunction and passing your reducer as an argument. TheProvidercomponent is wrapped around our App component so that any components within our app will have access to thestorewhich we pass to theProvidercomponent as a prop.

import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import App from "./App";
import reducers from "./reducers";

const store = createStore(reducers);

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

actions.js

The actions.js file contains our Redux actions. Each action is a plain JavaScript object that has a type field. From theRedux Documentation"You can think of an action as an event that describes something that happened in the application."In our case we have two actionssignInandsignOutwith their respective types"SIGN_IN"and"SIGN_OUT".

export const signIn = () => {
  return {
    type: "SIGN_IN",
  };
};

export const signOut = () => {
  return {
    type: "SIGN_OUT",
  };
};
React JSX

reducers.js

The reducers.js file is where the state is actually changed. First theINITIAL_STATEis declared with a special all caps syntax and the isSignedInstateis set to the string "no". Now we export default an anonymous function that takes two arguments.state = INITIAL_STATEand ouractionobject. We then use a switch statement to switch between the two cases we described in our actions file"SIGN_IN"and"SIGN_OUT". Now Redux has a rule that you cannot modify the existing state. Instead, they must make immutable updates, by copying the existingstateand making changes to the copied values. One of the easiest ways to do this is to use the Spread Operator, aka the three dots in front...state. The Spread Operator makes a copy of the original state so we can make changes to the new state object it has created. In our case we simply update the string to say "yes" for"SIGN_IN"and "no" for"SIGN_OUT". We then set the default case to return thestateunchanged.

const INITIAL_STATE = {
  isSignedIn: "no",
};

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case "SIGN_IN":
      return { ...state, isSignedIn: "yes" };
    case "SIGN_OUT":
      return { ...state, isSignedIn: "no" };
    default:
      return state;
  }
};
React JSX

App.js

Now our App.js file is where we see all these pieces come together.
import { connect } from "react-redux"
import { signIn, signOut } from "./actions";
So lets break down each piece in the order they appear. First we have two event handler functions that call our actionssignInandsignOut. Those two functions are assigned to two onClick events for our Sign In and Sign Out buttons. Then we have an h3 tag displaying{this.props.isSignedIn}. Now this may seem strange because we have been talking about state this whole time. The reason we call{this.props.isSignedIn}instead of{this.state.isSignedIn}is because of the function below.mapStateToPropstakes in the entire store stateand is used to select the part of the data from the store that our connected component needs. It is called every time the store state changes. In our case our store only has one piece of state,isSignedIn. SomapStateToPropsassignsstate.isSignedInto the propisSignedInwhich is available in our App component as{this.props.isSignedIn}. The final piece is theconnect()function which we get from React-Reduxexport default connect(mapStateToProps, { signIn, signOut })(App);This function takes two argumentsmapStateToPropsand the actions you will be using in this component, in our casesignInandsignOut. By passing our actions toconnect()they will automatically be dispatched to the store, which is the redux way of saying the store will be updated when their called. AKAisSignedInwill update in the store when they are called. Which leads me to the second benefit of connect(), by passing our actions to it our component receives them as props. This is why we can call them in the way we didthis.props.signIn()andthis.props.signOut(). Lastly we wrap our Appcomponent so it will still be exported as it normally would be but with the added logic coming from Redux and React-Redux.

import React from "react";
import { connect } from "react-redux";
import { signIn, signOut } from "./actions";

class App extends React.Component {
  signInClick = () => {
    this.props.signIn();
  };
  signOutClick = () => {
    this.props.signOut();
  };
  render() {
    return (
      <>
        <h3>Press the Buttons Below To Sign In or Sign Out</h3>
        <button onClick={this.signInClick}>Sign In</button>
        <button onClick={this.signOutClick}>Sign Out</button>
        <h3>Are you signed in?: {this.props.isSignedIn}</h3>
      </>
    );
  }
}
const mapStateToProps = (state) => {
  return { isSignedIn: state.isSignedIn };
};

export default connect(mapStateToProps, { signIn, signOut })(App);
React JSX