text: At some point in your complex React project, you are going to need a state management library. Redux is a good choice because of it's simplicity and centralized data management. This piece is a practical approach to the fundamentals of Redux in building React application for managing a book store.
  If you are unfamiliar with the Redux idea/philosophy, Carly Kubacak previous article will prepare you for this so I suggest you have a look at it first.
  When to Use Redux
  We have been writing about React with consumable examples without having to seek the assistant of a state management utility. So why now?
  Table of Contents
  Pete Hunt said if you ever doubt if you need Redux or not then you do not need it. On another hand, if your app is complex and fall into any of the following, then you should consider Redux:
  If you ever doubt if you need Redux or not then you do not need it. - Pete Hunt
  - Non-hierarchical data structure
  - Multiple events and actions
  - Complex component interaction
  Boilerplate with Slingshot
  DRY is my favorite principle in software engineering and I bet you like the idea too. For that reason, we are not going to write boilerplate code to get started, rather, we will use an existing solution.
  Cory House's Slingshot is awesome and covers everything you will need in a React-Redux app including linting, testing, bundling, etc. It is also has a high acceptance in the community with over 4k stars on GitHub.
  Clone Slingshot to your favorite working directory with the following:
  git clone book-store
  We need to prepare the cloned repository by installing dependencies and updating the
  package.json. Cory included an npm command to do all that:
  npm run setup
  You can run the app now with
  npm start -s
  The
  -s flag reduces noise in the console as Webpack which is the bundler will throw a lot of details about bundling to the console and that can be noisy and ugly.
  We do not need the app in the application so we can just remove it with a single command:
  npm run remove-demo
  We are good to start building our app.
  React with Redux Flow
  Before we dig deep into building our application, let's have a shallow approach by building a book manage page that creates a book with a form and lists the books. It's always important to keep the following steps in mind so you can always refer to it when building a React app with Redux:
  - Create Components
  - Create relevant actions
  - Create reducers for the actions
  - Combine all reducers
  - Configure store with
  createStore
  - Provide store to root component
  - Connect container to redux with
  connect()
  This tutorial is multi-part. What we will cover in this part is getting comfortable with this flow and then in the following parts we will add more complexity.
  We will make some of the pages available using React Router but leave a dumb text in them. We will just be making use of the manage book page.
  If you are unfamiliar with the difference between UI/Presentation components and Container components, I suggest you read our previous post.
  1. Create Components (with routes)
  Let us create 3 components: home, about and manage page components. We will put these components together to make a SPA using React Router which we covered in full details in a previous post
  Home Page: Create a file file named
  HomePage.js in
  ./src/components/common with the following:
  // ./src/components/common/HomePage.js import React from 'react'; const Home = () => { return ( <div> <h1>Home Home;
  About Page: Just like the home page but with a slightly different content:
  // ./src/components/common/AboutPage.js import React from 'react'; const About = () => { return ( <div> <h1>About About;
  Book Page: This page will contain everything for creating and listing books. We won't abstract Ui components for now. We go against good practice and put all our codes here then with time refactor. This is just for clarity.
  // ./src/components/book/BookPage.js import React from 'react'; class Book extends React.Component{ constructor(props){ // Pass props back to parent super(props); } // Submit book handler submitBook(input){ alert('Submitted') } render(){ // Title input tracker let titleInput; // return JSX return( <div> <h3>Books</h3> <ul> {/* Traverse books array */} {this.props.books.map((b, i) => <li key={i}>{b.title}</li> )} </ul> <div> <h3>Books Form</h3> <form onSubmit={e => { // Prevent request e.preventDefault(); // Assemble inputs var input = {title: titleInput.value}; // Call handler this.submitBook(input); // Reset form e.target.reset(); }}> <input type="text" name="title" ref={node => titleInput = node}/> <input type="submit" /> </form> </div> </div> ) } } export default Book;
  Root: We will create a root component now to house each of the other page components. React Router will also come into play here as we will use the
  Link component for navigation purposes:
  // ./src/components/App.js import React from 'react'; import {Link} from 'react-router'; const App = (props) => { return ( <div className="container"> <nav className="navbar navbar-default"> <div className="container-fluid"> <div className="navbar-header"> <a className="navbar-brand" href="#">Scotch Books</a> </div> <div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul className="nav navbar-nav"> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> <li><Link to="/books">Book</Link></li> <li><Link to="/cart">Cart</Link></li> </ul> </div> </div> </nav> {/* Each smaller components */} {props.children} </div> ); }; export default App
  We are using a functional component here which is one of the ways to create a React component. Passing the children down is a good way to inject the child components as determined by the router.
  Routes: Let's now create component routes for this application. The file that will contain the routes can be at the root of your project if the project is a small one or you can split them up if you prefer to:
  // ./src/routes.js import React from 'react'; import {Route, IndexRoute} from 'react-router'; import Home from './components/common/HomePage' import About from './components/common/AboutPage' import Book from './components/book/BookPage' import App from './components/App' export default ( <Route path="/" component={App}> <IndexRoute component={Home}></IndexRoute> <Route path="/about" component={About}></Route> <Route path="/books" component={Book}></Route> </Route> );
  You can see how the parent route is using
  App as it's component so all the children routes' component will be rendered where
  props.children is found in
  App component.
  Entry: The entry point will render the application with it's routes to the DOM using
  ReactDOM's render method:
  // ./src/index.js // Babel polyfill will emulate a full // ES2015 environemnt so we can enjoy goodies like // Promises import 'babel-polyfill'; import React from 'react'; import { render } from 'react-dom'; import { Router, browserHistory } from 'react-router'; import routes from './routes'; import '../node_modules/bootstrap/dist/css/bootstrap.min.css'; render( <Router routes={routes} history={browserHistory} />, document.getElementById('app') );
  We are passing all the routes to the router as a property which is one way of defining Router's routes. As a reminder, if these routing terms are strange to you, I recommend you read a post on React Router.
  At this point we are setup but our app will run with errors because the books props passed on to the
  Bookpage component is undefined. Let's keep moving though.
  2. Actions
  The next step as listed above is to identify relevant actions and create them. Actions are object payloads that are identified by a required property
  type. Action creators are methods that wrap and return the action object. At the moment, we just need an action which we will create in the
  actions folder in the
  src directory:
  // ./src/actions/bookActions.js export const createBook = (book) => { // Return action return { // Unique identifier type: 'CREATE_BOOK', // Payload book: book } };
  Now this action is ready to be dispatched by the store but no rush yet. Let's create the reducer that updates the store first.
  3. Reducers
  Reducers are used to update the state object in your store. Just like actions, your application can have multiple reducers. For now, we just need a single reducer:
  // ./src/reducers/bookReducers.js export default (state = [], action) => { switch (action.type){ // Check if action dispatched is // CREATE_BOOK and act on that case 'CREATE_BOOK': state.push(action.book); default: return state; } };
  When the store dispatched an action, all the reducers are called. So who do we know which action to act on? By using a Switch statement, we determine which action was dispatched and act on that.
  There is a big problem though. Reducers must be pure functions, which means they can't mutate data. Our current implementation of the reducer is mutating the array:
  // ./src/reducers/bookReducers.js // ... state.push(action.book); // ...
  How do we make an update without mutating? The answer is to create another array of data and update it's content with the previous state and that changes made:
  // ./src/reducers/bookReducers.js export default (state = [], action) => { switch (action.type){ case 'CREATE_BOOK': return [ ...state, Object.assign({}, action.book) ]; default: return state; } };
  The spread operator just pours out the content on the array into the new array.
  4. Combine Reducers
  I mentioned in the previous step that we could have as much reducers as we want but unlike actions, Reducers are not independent and can't standalone. The have to be put together and passed as one to the store. The act of putting multiple reducers together is known as reducer combination and the combined reducer is the root reducer.
  It's ideal to combine reducers at the root of the reducers' folder:
  // ./src/reducers/index.js import { combineReducers } from 'redux'; import books from './bookReducers' export default combineReducers({ books: books, // More reducers if there are // can go here });
  The combination is done with
  combineReducers() from the Redux library.
  5. Configure Store
  The next step is shifting focus from reducers to store. This is the time to create your store and configure it with the root reducer, initial state and middleware if any:
  // ./src/store/configureStore.js import {createStore} from 'redux'; import rootReducer from '../reducers'; export default function configureStore(initialState) { return createStore(rootReducer, initialState); }
  We do not need any middleware now so we just leave that out. The
  createStore method from
  redux is used to create the store. The createStore method is wrapped in an exported function
  configureStore which we will later use to configure provider.
  6. Provide Store
  The Redux's store API includes (but not all):
  /* Dispatches actions */ store.dispatch() /* Listens to dispatched actions */ store.subscribe() /* Get state from store */ store.getState()
  It is very inconveniencing to have to use this methods all around your react components. Dan, the founder of Redux built another library react-redux to help remedy this problem. All you need to do is import the
  Provider component from
  react-redux and wrap your entry point component with it:
  // ./src/index.js import 'babel-polyfill'; import React from 'react'; import { Provider } from 'react-redux'; import { render } from 'react-dom'; import { Router, browserHistory } from 'react-router'; import routes from './routes'; import '../node_modules/bootstrap/dist/css/bootstrap.min.css'; import configureStore from './store/configureStore'; const store = configureStore(); render( <Provider store={store}> <Router routes={routes} history={browserHistory} /> </Provider>, document.getElementById('app') );
  Not only do we wrap with
  Provider, we can now provide the
  store to the
  Provider component that will in turn give the descendants of the this entry component access to the store.
  7. Connect
  Wrapping our entry component with
  Provider does not mean we can go home happy. There is still a little job to be done. We need to pass down the states to our components props, same goes with the actions.
  Best practice demands that we do this in container components while convention demands that we us
  mapStateToProps for states and
  mapDispatchToProps for actions.
  Let's update the
  BookPage container component and see how the flow gets completed:
  // ./src/components/book/BookPage.js import React from 'react'; import { connect } from 'react-redux'; import * as bookActions from '../../actions/bookActions'; class Book extends React.Component{ constructor(props){ super(props); } submitBook(input){ this.props.createBook(input); } render(){ let titleInput; return( <div> <h3>Books</h3> <ul> {this.props.books.map((b, i) => <li key={i}>{b.title}</li> )} </ul> <div> <h3>Books Form</h3> <form onSubmit={e => { e.preventDefault(); var input = {title: titleInput.value}; this.submitBook(input); e.target.reset(); }}> <input type="text" name="title" ref={node => titleInput = node}/> <input type="submit" /> </form> </div> </div> ) } } // Maps state from store to props const mapStateToProps = (state, ownProps) => { return { // You can now say this.props.books books: state.books } }; // Maps actions to props const mapDispatchToProps = (dispatch) => { return { // You can now say this.props.createBook createBook: book => dispatch(bookActions.createBook(book)) } }; // Use connect to put them together export default connect(mapStateToProps, mapDispatchToProps)(Book);
  mapStateToProps now makes it possible to access the books state with
  this,props.books which we were already trying to do in the component but was shy to run because we were going to see red in the console.
  mapDispatchToProps also returns an object for the respective dispatched actions. The values are functions which will be called when the actions are dispatched. The value expects a payload which you can pass in as well when dispatching.
  The
  connect method now takes in these 2 functions and returns another functions. The returned function is now passed in the container component.
  Now you can run the app with:
  npm start -s
  We should have a working demo like the one in the image below:
  Up Next...
  We just had a quick look on React with Redux but this can make a real app. In the next part of this tutorial, we will try to draw closer to something real like making async requests with
  redux-thunk