45,59 €
Build consistent web apps with Redux by easily centralizing the state of your application.
This book targets developers who are already fluent in JavaScript but want to extend their web development skills to develop and maintain bigger applications.
The book starts with a short introduction to the principles and the ecosystem of Redux, then moves on to show how to implement the basic elements of Redux and put them together. Afterward, you are going to learn how to integrate Redux with other frameworks, such as React and Angular.
Along the way, you are going to develop a blog application. To practice developing growing applications with Redux, we are going to start from nothing and keep adding features to our application throughout the book. You are going to learn how to integrate and use Redux DevTools to debug applications, and access external APIs with Redux. You are also going to get acquainted with writing tests for all elements of a Redux application. Furthermore, we are going to cover important concepts in web development, such as routing, user authentication, and communication with a backend server
After explaining how to use Redux and how powerful its ecosystem can be, the book teaches you how to make your own abstractions on top of Redux, such as higher-order reducers and middleware.
By the end of the book, you are going to be able to develop and maintain Redux applications with ease. In addition to learning about Redux, you are going be familiar with its ecosystem, and learn a lot about JavaScript itself, including best practices and patterns.
This practical guide will teach you how to develop a complex, data-intensive application leveraging the capabilities of the Redux framework.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 333
Veröffentlichungsjahr: 2017
BIRMINGHAM - MUMBAI
Copyright © 2017 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: August 2017
Production reference: 1260817
ISBN 978-1-78646-239-8
www.packtpub.com
Author
Daniel Bugl
Copy Editor
Dhanya Baburaj
Reviewer
Sergii Shvager
Project Coordinator
Devanshi Doshi
Commissioning EditorWilson D'souza
Proofreader
Safis Editing
Acquisition Editor
Shweta Pant
Indexer
Mariammal Chettiyar
ContentDevelopmentEditor
Roshan Kumar
Graphics
Jason Monteiro
Technical Editors
Akansha BathijaBharat Patil
Production Coordinator
Shraddha Falebhai
Daniel Bugl is a developer, product designer and entrepreneur, focusing on web technologies. He currently lives in Vienna, Austria. He got into programming via game development as early as the age of 6. Later, at the age of 10, he first learned about web technologies such as HTML, CSS, PHP, and JavaScript.
During high-school, he contributed to the Ubuntu project, specifically the Ubuntu Beginners Team, supporting beginners with Linux and helping them get started with the community. He mentored some people who are full Ubuntu members now. He was also part of the Ubuntu-Youth council and leading the Ubuntu Austria LoCo (Local Community). Furthermore, he developed open source software, voluntarily translated software, and supported people on askubuntu.
He also did an internship as a researcher at the Vienna University of Technology, which would later become the university he studies at. Later on, he did an internship at Jung von Matt, an advertisement agency, where he collected practical experience in web development by developing a management panel.
He is now studying Business Informatics and Information Systems at the Vienna University of Technology (TU Wien) and is in the process of writing his bachelor thesis. At the university, he sometimes works as a tutor, on the Program Construction (entry-level programming), Usability Engineering, and Interface and Interaction Design courses.
Now, he is a contributor to many open source projects (including Redux and his own library, redux-undo) and a member of the React community on the Redux team. He also founded and still runs his own hardware/software startup TouchLay (touchlay), which helps other companies present their products and services. At his company, he constantly works with web technologies, especially React and Redux.
First of all, I would like to thank all of the people involved in the production of this book. The team at Packt was very nice and pleasant to work with. I would also like to thank Dan Abramov for creating Redux, helping me create redux-undo, and letting me create a recipe page in the Redux documentation. Him and his projects have been a great inspiration to me.
Furthermore, I would like to thank Nik Graf, Max Stoiber, and Andrey Okonetchnikov for organising the React Vienna Meetup, which deepened my interest in React and Redux. Special thanks for letting me give a talk on higher-order reducers! I would also like to thank my co-founder, Georg Schelkshorn, for running an amazing company with me – I would not get to use web technologies as much without it.
Finally, I would like to thank my family and friends for supporting me during the creation of this book. At this point, I would especially like to thank and send love to my girlfriend, Destiny Rebuck, for supporting me and caring for me during the most stressful part of the process--the weeks before publishing.
Sergii Shvager is a frontend developer who is passionate about React/Redux. He was born in Ukraine and is currently living in Berlin. He has worked on the frontend part of projects in different areas, such as e-commerce, game development, and services. He started his frontend experience with jQuery, Backbone.js, and Ext.js, and then switched to React/Redux stack.
He has had his own company that develops mobile applications. Currently, he is working at eBay Classified Group.
For support files and downloads related to your book, please visit www.PacktPub.com. Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review on this book's Amazon page at www.amazon.com/dp/1786462397.
If you'd like to join our team of regular reviewers, you can e-mail us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Preface
About the book
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code
Downloading the color images of this book
Errata
Piracy
Questions
Why Redux?
Defining the application state
Defining actions
Tying state and actions together
Redux' three fundamental principles
Single source of truth
The read-only state
State changes are processed with pure functions
Introduction to the Redux ecosystem
Summary
Implementing the Elements of Redux
The Redux cycle
An action is dispatched
The main reducer function gets executed
Redux saves the new state
Strictly unidirectional data flow
Running code examples
Setting up a new project
Setting up Node.js
Initializing the project
Setting up webpack
Setting up Babel
Setting up the entry files
Running webpack
Setting up Redux
The template code
Implementing actions and action creators
Separating action types
ES2015 - import/export
Introducing action creators
ES2015 - arrow functions
ES2015 - import/export
Code example
Implementing reducers
Defining/importing action types
Defining action creators
Writing the posts reducer
The main structure of a reducer
ES2015 - using destructuring and the rest operator to parse the action
Handling CREATE_POST – creating a new post
Handling EDIT_POST – editing posts
Testing out our reducer
Writing the filter reducer
Combining reducers
Testing out the full reducer
Code example
The store – combining actions and reducers
Creating the store
Subscribing to state changes
Dispatching actions
Rendering the user interface
Creating sample data
Handling the user input
Code example
Summary
Combining Redux with React
Why React?
The principles of React
Setting up React
Rendering simple text
Rendering with JSX
Setting up JSX
Using JSX
Example code
First steps with React
Creating a simple React element
Creating a static React component
Functional components
Using components
Example code
Class components – dynamic React components
Creating a static class component
Creating a dynamic class component
Setting the initial state
React life cycle methods
Updating the state
Example – dynamic React component with timer
Example code
Connecting React to Redux
Presentational versus container components
Writing presentational components
Post component
PostList component
Example code
Writing container components
Implementing our own container component
Example code
Using React-Redux bindings to create a container component
Setting up React-Redux
Using React-Redux to create a container component
Using selectors
Example code
Building an application with Redux and React
The goal
Project structure
Defining the application state
Users state
Posts state
Filter state
Defining action types and action creators
Defining action types
Defining action creators
User action creators
Post action creators
Filter action creators
Implementing reducers
Users reducer
Posts reducer
Filter reducer
Root reducer
Setting up the Redux store
Code example – Redux-only application
Implementing the user interface
Implementing presentational components
User component
Post component
Timestamp component
PostList component
Filter component
FilterList component
Implementing container components
ConnectedPostList component
ConnectedFilterList component
Implementing the App component
Using <Provider>
Rendering the App component
Code example – React/Redux application
Further tasks
Summary
Combining Redux with Angular
Redux with Angular 1
Setting up Angular 1
Code example
Creating a basic Angular 1 application
Defining the module and controller
Code example
Setting up ng-redux
Redefining the controller
Dispatching actions from the user interface
Code example
Redux with Angular 2+
Setting up Angular 2+
Setting up @angular-redux/store
Code example
Summary
Debugging a Redux Application
Integrating Redux DevTools
Installing Redux DevTools
Creating a DevTools component
Connecting DevTools to Redux
Using the DevTools.instrument() store enhancer
Rendering DevTools
Implementing the persistState() store enhancer
Using multiple store enhancers
Implementing a simple session key provider
Do not re-dispatch on refresh
Using the store enhancer
Excluding Redux DevTools in production
Injecting the NODE_ENV environment variable with webpack
Adding new build scripts for production and development
Separating the production store from the development store
Implementing the development store
Implementing the production store
Importing the correct store
Importing and using configureStore()
Only loading the DevTools component in development mode
Running in production/development mode – example code
Setting up hot reloading
Hot reloading React components
Hot reloading other code with webpack
Hot reloading Redux reducers
Testing out hot reloading – example code
Using Redux DevTools
DockMonitor
Setup
Properties
LogMonitor
Setup
Usage
Properties
Inspector
Setup
Usage
Properties
SliderMonitor
Setup
Usage
Properties
ChartMonitor
Setup
Properties
Other monitors
Summary
Interfacing with APIs
Setting up the backend
The backend API
GET /api
Example output
GET /api/posts
Example output
GET /api/posts/:id
Example output
POST /api/posts
Example request
Example output
POST /api/posts/:id
Example request
Example output
GET /api/users
Example output
GET /api/users/:username
Example output
POST /api/users
Example request
Example output
POST /api/users/:username
Example request
Example output
Handling asynchronous operations with Redux
Dispatching multiple actions from an action creator
Defining action types
Creating an asynchronous action creator
Handling asynchronous action creators via middleware
Setting up redux-thunk middleware
Pulling data from an API into the Redux store
Extracting boilerplate code
Pulling posts from the API
Pulling users from the API
Fetching a single user
Fetching users when fetching posts
Handling loading state
Implementing the reducer
Implementing the component
Using the component
Handling error state
Implementing the reducer
Implementing the component
Using the component
Example code
Sending notifications to an API via Redux
Using asynchronous action creators
Creating users via the API
Creating posts via the API
Example code
Summary
User Authentication
JSON Web Tokens (JWT)
JSON Web Token structure
Header
Payload
Signature
Token
Using JSON Web Tokens
Implementing token authentication
Backend API
POST /api/login
Example request
Example output
POST /api/users
Example request
Example output
POST /api/posts
Example request
Example output
Secured routes
Storing the token in the Redux store
Defining the action types and action creator
Creating the reducer
Dispatching login action in the component
Testing out the login
Checking whether the user is logged in
Separating the header
Hiding/showing components when the user is logged in
Showing the currently loggedin user
Sending the token with certain requests
Example code
redux-auth
Summary
Testing
Setting up Jest
Testing automatically on every file change
Checking code coverage
Example code
Using Jest
Using test and describe
Matchers
.toBe or .not.toBe
Truthiness
Numbers
Strings
Arrays
Exceptions
All matchers
Testing asynchronous code
Callbacks
Promises
.resolves/.rejects
Setup and teardown
Running every time before/after each test
Running once before/after all tests
Scoping
Mocking
.mock property
Return values
Implementations
Special matchers
Testing Redux
Synchronous action creators
Reducers
Testing initial state
Initializing state with beforeEach()
Testing the setFilter action
Testing the clearFilter action
Reducers with async actions
Asynchronous action creators
Testing successful requests
Testing failing requests
Example code
Other tests
Testing React components
Summary
Routing
Creating a simple router
Defining the action types and action creator
Creating the reducer
Creating the page components
Creating the MainPage component
Creating the AboutPage component
Creating the Router component
Connecting the Router component to Redux
Using the Router component
Creating the Navigation component
Connecting the Navigation component to Redux
Using the Navigation component
Code example
Using a routing library
Introducing react-router
Static routing
Dynamic routing
Nested routes
More routing
Using react-router
Installing react-router
Defining the <Router> and <Route>
Defining the <Link>
Trying out the router
Marking the currently selected link
Using react-router with Redux
Do I need to connect my router to Redux?
Why deeply integrate my router with Redux?
Example code
Using react-router-redux
Installing react-router-redux
Using the routerMiddleware
Using the routerReducer
Using the ConnectedRouter
Testing out the router
Navigating by dispatching actions
Example code
Summary
Rendering on the Server
Why render on the server?
Current process to load the page
Using server-side rendering
Preparing for server-side rendering
Using the isomorphic-fetch library
Implementing server-side rendering
Handling the request/routing
Emulating the Redux store and browser history
Initializing the Redux store
Using react-router to decide which page to render
Handling react-router redirects
Injecting rendered React components into the index.html template
Injecting the preloaded Redux store state
Rendering the template file
Using the preloaded Redux store state
Caching the index page
Performance improvements
Summary
Solving Generic Problems with Higher-Order Functions
Making functions pure
Simple side effects
No side effects
Other side effects
Side effects and Redux
Creating higher-order functions
Functions as arguments
Functions as results
Solving generic problems with Redux
Higher-order reducers
Higher-order action creators
Higher-order components
Implementing generic undo/redo Redux
Setting up the counter application
Looking at the counter reducer
Implementing undo/redo in the counter application
Defining the action types
Defining the action creators
Defining the new state
Rewriting the counter reducer
Handling the counter-related actions
Handling the undo/redo actions
Creating undo/redo buttons
Trying out undo/redo
Example code
Implementing a generic undo/redo higher-order reducer
Defining the undoable higher-order reducer
Defining the initial state
Problems with our previous solution
A new kind of history
Defining a generic initial state
Handling generic undo/redo actions
Defining the action types
Defining the action creators
Implementing the enhanced reducer
Handling the undo action
Handling the redo action
Handling other actions (updating the present state)
Removing undo/redo logic from the counter reducer
Wrapping the counter reducer with undoable
Problems with our simple undoable higher-order reducer
Example code
Implementing redux-undo
Installing redux-undo
Wrapping our reducer with undoable
Adjusting the state selector
Importing the undo/redo actions
Debug mode
Example code
Summary
Extending the Redux Store via Middleware
What is middleware?
Express middleware
Creating our own middleware pattern
Sketching out the API
Creating the Middleware class
Defining the run method
Defining the use method
Using our own middleware pattern
Example code
Using the Redux store middleware
Implementing logging
Manual logging
Wrapping the dispatch function
Monkeypatching the dispatch function
Hiding monkeypatching
Getting rid of monkeypatching
Applying middleware
Implementing Redux middleware
Creating a middleware folder
Logging middleware
Error reporting middleware
Applying our middleware to the Redux store
Example code
Thunk middleware
Final tips and tricks
Designing the application state
Using indices
Normalized state
Organizing data in the application state
Updating an application state
Updating nested objects
Common mistake 1 - New variables that point to the same objects
Common mistake 2 - Only making a shallow copy
Correct approach - Copying all levels of nested data
Updating arrays
Inserting items
Removing items
Updating items
Mutating copies
Using libraries
Summary
Redux is a predictable state container for JavaScript apps. It helps you write applications that run in different environments (client, server, and native) and are predictable and easy to test. Additionally, Redux provides a great developer experience, such as live code editing and time traveling debugging. Redux can be used together with a view library, like React and Angular.
This book will start out teaching you why and how Redux works. We are going to learn about principles and restrictions that make your application more predictable. Afterwards, we will implement the basic elements of Redux to create a blog application. Next, we will connect Redux to a user interface by combining it with a view library, like React and Angular. Then we move on by implementing common functionality in our Redux application, such as user authentication, interfacing with APIs, writing tests, and routing. Finally, we are going to discuss extending Redux itself, by solving common problems with state management (such as undo/redo functionality) through higher-order reducers and middleware.
After reading this book, you will be able to write maintainable, predictable, consistent, and easy-to-test applications with Redux and React.
Chapter 1, Why Redux?, will teach you about the principles that make Redux special, and why Redux should be used in a project. It starts out with the motivation behind Redux (complexity of state management), then briefly covers how Redux works in practice and how certain restrictions allow us to write maintainable, predictable, consistent, and easy-to-test applications.
Chapter 2, Implementing the Elements of Redux, explains how to set up a project that is ready for Redux and the new JavaScript ES2015 syntax. Then, you are going to implement the basic elements of Redux and put a full Redux project together.
Chapter 3, Combining Redux with React, covers what React is and why it makes sense to use it. Then you will learn how to set up a project with React and connect Redux to it.
Chapter 4, Combining Redux with Angular, covers using Redux in combination with Angular 1 and 2+ (compatible with Angular 4).
Chapter 5, Debugging a Redux Application, covers how to integrate and use Redux DevTools in an application. Then it covers various Redux DevTools monitors, explaining how to configure and use them in practice.
Chapter 6, Interfacing with APIs, teaches you how to handle asynchronous operations with Redux. Afterwards, this knowledge is used to pull blog posts and users from an API into the Redux store. Finally, you are going to learn how to dispatch actions that change the state in the frontend/client and the backend/server (creating users and posts).
Chapter 7, User Authentication, explains token authentication is and why using it over traditional cookie/session ID authentication makes sense. Next, you will learn how to use and implement an open standard of token authentication--JSON Web Token (JWT).
Chapter 8, Testing, covers using Jest, a testing engine, to write tests for all the elements of Redux.
Chapter 9, Routing, covers how to implement routing with Redux and React, manually and by using libraries such as react-router and react-router-redux.
Chapter 10, Rendering on the Server, this chapter teaches you why server-rendering makes sense and what benefits we get from using this technique. Then, you are going to learn how to implement server-side rendering in a Redux/React application.
Chapter 11, Solving Generic Problems with Higher-Order Functions, explains about advanced patterns when developing JavaScript/Redux/React applications. It starts by teaching basic concepts such as pure functions, then moves on to higher-order functions. Next, you will learn how to use these concepts in a Redux/React application to implement generic undo/redo behavior.
Chapter 12, Extending the Redux Store via Middleware, teaches what middleware (specifically, Redux store middleware) is and how it can be used. To wrap up, this chapter ends with a section on general tips and tricks for developing Redux applications.
Node.js v6.11.1 LTS
Needs to support nodejs (any Windows, macOS, Linux device)
This book is for web developers who are already fluent in JavaScript, but want to extend their skills to be able to develop and maintain growing applications.
In this book, you will find a number of text styles that distinguish between different kinds of information. Here are some examples of these styles and an explanation of their meaning. Code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "The next lines of code read the link and assign it to theBeautifulSoupfunction."
A block of code is set as follows:
{ "title": "Another test", "text": "Hello API!"}
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
{ "username": "des", "realname": "Destiny"
,
"password": "test123"
}
Any command-line input or output is written as follows:
npm install --save react react-dom
Feedback from our readers is always welcome. Let us know what you think about this book-what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of. To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you. You can download the code files by following these steps:
Log in or register to our website using your e-mail address and password.
Hover the mouse pointer on the
SUPPORT
tab at the top.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box.
Select the book for which you're looking to download the code files.
Choose from the drop-down menu where you purchased this book from.
Click on
Code Download
.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Learning-Redux. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from https://www.packtpub.com/sites/default/files/downloads/LearningRedux_ColorImages.pdf.
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books-maybe a mistake in the text or the code-we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title. To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy. Please contact us at [email protected] with a link to the suspected pirated material. We appreciate your help in protecting our authors and our ability to bring you valuable content.
If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.
If you have written a large-scale application before, you will know that managing application state can become a pain as the app grows. Application state includes server responses, cached data, and data that has not been persisted to the server yet.
Furthermore, the User Interface (UI) state constantly increases in complexity. For example, nowadays, routing is often implemented on the client so that we do not need to refresh the browser and reload the whole application in order to load a new page. Client-side routing is good for performance, but it means that the client has to deal with even more state (in comparison to using server-side routing).
As you can imagine, conflicts and inconsistencies in these various kinds of state can be hard to deal with. Managing all these states is hard and, if not managed correctly, application state can quickly grow out of control, like an untended garden.
If all of this was not bad enough, new requirements, such as optimistic updates and server-side rendering, become necessary to be able to keep up with the ever increasing performance demands.
State is difficult to deal with because we are mixing two concepts that can be very unpredictable when put together: Asynchronicity and Mutation.
Asynchronicity means that changes can happen anytime, in an asynchronous manner. For example, a user presses a button that causes a server request. We do not know when the server responds and, for performance reasons, we do not want to wait for the response. This is where Asynchronicity comes into play. We act on a response whenever it occurs, but it is unpredictable when this will happen.
Mutation means any change in the application state, such as storing the result from the server response in our application state or navigating to a new page with client-side routing, would change the value of the current route, mutating the application state.
When putting these two concepts together, bad things can happen. For example, the user might enter some new data and save it, while we are still persisting something else to the server, causing an inconsistent state.
This is where Redux comes in. Redux attempts to make state Mutations predictable, without losing the performance advantages of Asynchronicity. It does so by imposing certain restrictions on how updates can happen. These restrictions make applications predictable and easy to test.
As a result of these restrictions, Redux also provides a great developer experience. When debugging, you can time travel between previous application states, and pinpoint the exact time when a bug occurs. You can also use this functionality in production—when users report a bug, the whole application state can be transmitted. This means that you can load the exact state of the application when the bug occurred, making reproduction trivial:
Furthermore, Redux is very simple and uses plain JavaScript objects and functions. As a result, it can run in various different environments, such as a web client (browser), native applications, and even on the server.
To start out, we will cover the basic elements of a Redux application. Afterwards, we will also cover the restrictions mentioned earlier, resulting in the fundamental principles of Redux. Next, we will focus on how to use Redux with React, a library that shares similar principles and is used to generate user interfaces from the data maintained in Redux. Then, we will teach you how to use Redux with Angular, a framework that is also used to generate user interfaces. Next, we will dive deep into how to solve common problems in web development (such as debugging, user authentication, or interfacing with third-party APIs) with Redux:
Finally, we will discuss how to extend Redux by implementing generic solutions that work with all Redux applications. These generic solutions can be distributed as libraries and there are already many of these out there. For example, to implement undo/redo functionality in any application, you simply use a library, and it will work, regardless of how your application is structured.
In this book, we will develop a blog application with Redux. This application will keep getting extended throughout the chapters and help us practice concepts learned in the book.
In this chapter, we will cover:
Defining the state of our application
Defining actions
Tying the state and actions together
Learning about Redux's three fundamental principles
Introducing the Redux ecosystem
Before we start implementing a Redux application, we first have to think about the application state. The state of a Redux application is simply a JavaScript value (usually an object).
The application state includes all data needed to render the application and handle user actions. Later, we will use parts of the application state to render HTML templates and make API requests.
You might not know the full application state in the beginning; that's fine. We will make sure that we design our application state in an extendable way. In a Redux application, the state is usually represented as a JavaScript object. Each property of the object describes a substate of the application.
For example, a simple blog application state could consist of an array of posts (which are written by the user and contain some text):
{ posts: [ { user: 'dan', text: 'Hello World!' }, { user: 'des', text: 'Welcome to the blog' } ] }
Imagine that we want to add a category string to posts later—we can simply add this property to the objects in the posts array:
{ posts: [ { user: 'dan',
category: 'hello',
text: 'Hello World!' }, { user: 'des',
category: 'welcome',
text: 'Welcome to the blog' } ] }
Now, let's say we want to implement filtering posts by category; we could extend our state object with a filter property that stores the category as a string:
{ posts: [ { user: 'dan', category: 'hello', text: 'Hello World!' }, { user: 'des', category: 'welcome', text: 'Welcome to the blog' } ]
,
filter: 'hello'
}
We can reconstruct the whole application state from this object. Being able to do this is one of the things that makes Redux so awesome.
In a later chapter, we will observe how to add the logic that actually filters posts by making use of the application state.
You might think that the application state will become a very complicated object at some point, and that's true—but in a more advanced project; the state won't be defined in a single file. Application state can be split up and dealt with in multiple files (a separate file for each substate), then combined together.
To keep things simple, let's define our application state as an array of posts for now:
[ { user: 'dan', category: 'hello', text: 'Hello World!' }, { user: 'des', category: 'welcome', text: 'Welcome to the blog' } ]
Now that we have defined the state of our application, we also need a way to change the state. In Redux, we never modify the state directly. To ensure that the application is predictable, only actions can change the state. Redux actions are simply JavaScript objects, with a type property that specifies the name of the action. Let's say we want to create a new post in our blog, we could use an action like this:
{ type: 'CREATE_POST', user: 'dan', text: 'New post' }
Later on, we could define another action for setting the filter:
{ type: 'SET_FILTER', filter: 'hello' }
These action objects can be passed to Redux, resulting in a new state being calculated from the current state and the action. This process is called dispatching an action.
The way state changes are processed in Redux makes them very explicit, clear, and predictable. If you want to find out how a certain state change happened, just look at the action that was dispatched. Furthermore, you can reproduce state changes by reverting and redispatching actions (also known as time traveling).
As mentioned earlier, Redux is based on certain principles and restrictions. The API of Redux is very small and only consists of a handful of functions. These principles and restrictions are what makes Redux so powerful, and you need to stick to them to be able to reap all the benefits of Redux.
We will now discuss the three fundamental principles of Redux:
Single source of truth
Read-only state
State changes are processed with pure functions
Redux consists of a single store, which is a JavaScript value containing the entire state of your application. A single source of truth comes with a lot of benefits:
In traditional applications, the state is stored in different places across the whole application. With a single source of truth, debugging becomes easy, as you simply have one value to look at.
It is easy to create universal apps, as you can serialize the application state on the server and send it to the client without much effort.
Generalized functionalities, such as undo/redo, become easy to implement. For example, you can simply drop in a library that turns (a part of) your state into an
undoable
state.
To access the application state, Redux provides a .getState() function on the store object. You can view the full state, as follows:
console.log(store.getState())
The output of the preceding code will be the application state. In our example application, the output would be the post array we defined earlier:
[ { user: 'dan', text: 'Hello World!' },
