Redux in action pdf free download






















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 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. Style and approach This practical guide will teach you how to develop a complex, data-intensive application leveraging the capabilities of the Redux framework.

This clearly written, example-rich book begins by introducing you to React, diving into some of the fundamental ideas in React, and working with components. In the second section, you'll explore the different ways that data works in React as well as learning more about components. You'll also find several useful appendixes covering related topics like React tooling and the React ecosystem. About the Technology Facebook created React to help deliver amazing user experiences on a website with thousands of components and an incomprehensible amount of traffic.

The same powerful tools are available to you too! The key is a clever design for managing state, data flow, and rendering, so your application is easy to think about and runs smoothly. Add an incredibly rich ecosystem of components and libraries, and you've got a recipe for building web apps that will delight both developers and users. You'll master core topics like rendering, lifecycle methods, JSX, data flow, forms, routing, integrating with third-party libraries, and testing.

And the included application design ideas will help make your apps pop. As you learn to integrate React into full-stack applications, you'll explore state management with Redux and server-side rendering, and even dabble in React Native for mobile UIs. What's Inside React from the ground up Implementing a routing system with components Server-side rendering in Node.

He loves clean code, beautiful systems, and good coffee. React and Redux now offer an easier, more elegant solution. Geary shows how React bindings for Redux enable you to separate stateless presentation components from components that are connected to React.

You'll learn how react-redux bindings can automatically connect to the Redux store, and how they enforce good programming practice by separating concerns between containers and their associated stateless components. Geary also illustrates advanced aspects of Redux through a complex application example.

The only up-to-date and comprehensive guide to React and Redux, Building React. We will then add important middleware and set up immutableJS in our application. We will explore the use of react-router-dom and its functions. We will create a list of routes that we will need in order to create our application, and explore routing on the server site and create the required routes for our application.

We will then debug our application and integrate Redux Dev tools. We will dive into a modern approach to structuring our server site components in terms of Model, Controller, Helper functions, and utilities functions. Finally, we will venture into the possibilities of extending the application for further research, including deployment and optimization. What you will learn Follow the test-driven development TDD approach to develop a single-page application Add important middleware, such as Redux store middleware, redux-saga middleware, and language middleware, to your application Understand how to use immutableJS in your application Build interactive components using ReactJS Configure react-router-redux and explore the differences between react-router-dom and react-router-redux Use Redux Dev tools to debug your application Set up our API server and create the API required for our application Who this book is for This book is meant for JavaScript developers interesting in learning state management and building easy to maintain web applications.

If you want to learn React and Redux by example this is a book you would like. We are going to build several applications with an incremental level of complexity by going through the same steps.

The unidirectional flow implies getting the initial state, showing it to the user using the view functions, listening for actions, updating the state based on those actions, and rendering the updated state back to the user again. In all application we will identify these concepts: The state - the data that is stored and can change. The views - functions transform the data into HTML.

React makes it easier to create view functions that take input data and - return the visual representation of it using an XML-like syntax called JSX. Actions - plain data objects used to express user interaction. The updaters - functions transform the state.

They receive the current state and an action and return the new state. The Redux library provides a functional approach for managing state using pure update functions. Authors Alex Banks and Eve Porcello show you how to create UIs with this small JavaScript library that can deftly display data changes on large-scale, data-driven websites without page reloads.

Developed by Facebook, and used by companies including Netflix, Walmart, and The New York Times for large parts of their web interfaces, React is quickly growing in use. The book dives deeply into state management in React. You will learn everything about React's local state and state management with Redux and MobX. It comes with a lot of best practices, techniques and concepts. Along the way you will have practical hands on experiences by building own applications.

The book turned out to exceed all my expectations. What started as an attempt to write a introductory book about state management in React with Redux, turned out into a full blown page book which showcases MobX as alternative state management library, implements exciting applications along the way and has boilerplate projects to get you started in learning and building applications with these libraries. The bigger idea was to write a book which gives learners a consistent way to study the topic state management.

I had the feeling that there exist way too many, partly inconsistent or outdated, tutorials around these topics and it is hard for learners to choose from so many opportunities.

I thought, one well structured book should help newcomers to get started easily in the topic of state management with React's local state, Redux and MobX.

The book teaches you how to use local state in React and scaling React applications with advanced practices, patterns and techniques. Afterward, the ebook dives into learning Redux and MobX as libraries for state management. These libraries are taught from scratch without React but in combination with React later on. However, all these learnings are not necessarily bound to React as view layer library.

They can be applied in other view layer component based libraries, such as Vue. If you are new to React and want to learn React before, I recommend you to read the up to date book The Road to learn React. We have a single store to control the state, actions to describe the changes we want to make, reducers services, in our example that know how to mutate the state based on the requested action, and middleware to handle the housekeeping tasks.

What makes Redux special, and sometimes hard to understand, is that reducers never change the state in our case, the recipe book , since it is immutable. Instead, the reducers must create a new copy of the book, make the needed changes to the copy, and return the new, modified book to the store. This approach allows Redux and the view layers to easily do change detection.

In later chapters we will discuss in detail why and how this approach is used. It is important to note that the whole application state is kept in a single location, the store. Having a single source of data provides enormous benefits during debugging, serialization, and development, as will become apparent in the examples in this book.

Reducers Once an action is sent to the store, the store needs to figure out how to change the state accordingly. In real Redux applications, there will be one root reducer function that will call additional reducer functions to calculate the nested state.

Middleware Middleware is a more advanced feature of Redux and will be discussed in detail in later chapters. The middleware act like interceptors for actions before they reach the store: they can modify the actions, create more actions, suppress actions, and much more.

Since the middleware have access to the actions, the dispatch function, and the store, they are the most versatile and powerful entities in Redux.

Store Unlike many other Flux implementations, Redux has a single store that holds the application information but no user logic. The role of the store is to receive actions, pass them through all the registered middleware, and then use reducers to calculate a new state and save it. When it receives an action that causes a change to the state, the store will notify all the registered listeners that a change to the state has been made.

This will allow various parts of the system, like the UI, to update themselves according to the new state. Chapter 1.

Understanding these concepts is crucial to understanding the underlying principles of Redux. Functional programming has become a trendy topic in the web development domain lately, but it was invented around the s.

The paradigm centers around avoiding changing state and mutable data—in other words, making your code predictable and free of side effects. JavaScript allows you to write code in a functional style, as it treats functions as first-class objects. This means you can store functions in variables, pass them as arguments to other functions, and return them as values of other functions. But since JavaScript was not designed to be a functional programming language per se, there are some caveats that you will need to keep in mind.

In order to get started with Redux, you need to understand pure functions and mutation. Pure and Impure Functions A pure function returns values by using only its arguments: it uses no additional data and changes no data structures, touches no storage, and emits no external events like network calls. This means that you can be completely sure that every time you call the function with the same arguments, you will always get the same result.

JavaScript has limited tooling for managing immutable objects, and we are often required to use external libraries. To make the colors object appear immutable, we can use the Object. If you thought that the value should be ' FF', you missed that we changed the red property before we froze the object. This is a good example of how easy it is to miss this kind of thing in real applications.

Here, once we used Object. In practice things are often more complicated, though. JavaScript does not provide good native ways to make data structures fully immutable. For example, Object. We will talk about different immutable libraries later in the book. Redux and React Redux started out as a companion to React, but has started to gather a major following with other frameworks like Angular.

At its base Redux is fully framework-agnostic, and it can easily be used with any JavaScript framework to handle state and changes. Core Concepts of Flux and Redux 15 The connection to different frameworks is done with the help of third-party libraries that provide a set of convenience functions for each framework in order to seamlessly connect to Redux.

The library that we will use to connect Redux and React is called react-redux, and we will be covering it extensively later in the book. Basic Redux Implementation People love Redux because of its simplicity. In fact, it is so simple that we can implement most of it in a handful of lines of code. Thus, unlike with other frameworks, where the only way to learn is to study the API, here we can start by implementing Redux ourselves.

The basic premise behind Redux is the idea that all the application state is saved in one place, the store. To use this idea in applications we will need to find a way to: 1. Modify the state as a result of events user-generated or from the server. Monitor state changes so we can update the UI. The first part can be split into two blocks of functionality: 1.

Notify the store that an action has happened. We are going to have two buttons that allow us to increment and decrement a simple counter, and a place where we can see the current counter value: The index. For that, we will use the subscribe function, which we will also implement a bit later.

Core Concepts of Flux and Redux 17 still one thing missing. How will our mini-Redux know how to handle the events and change the application state?

For this, we define an additional function. On each action dispatched, Redux will call our function, passing it the current state and the action. The job of the reducer will be to understand the action and, based on it, create a new state.

This is the reducer we mentioned before. The dispatch function calls the reducer implemented by the application creator, passing it both the current state and the action it received. This information should be enough for the reducer function to calculate a new state. We will be using a simple comparison by reference to check whether the state has changed. One remaining task is to notify our view of the state change.

The only change that needs to be made to the reducer is the switch statement. Instead of doing: Previous reducer code 1 switch action Changes to New reducer code 1 switch action. The Redux store will also give us all the features we implemented ourselves before, like subscribe and dispatch. Thus, we can safely delete these methods. Core Concepts of Flux and Redux 20 Subscribing to store updates 1 store.

As mentioned previously, our actions now need to have the type property. We also learned a bit about basic functional programming principles, such as pure functions and immutability. As they are very important for our real-world applications, we will talk about these concepts more later in the book. In the next chapter we are going to see how to actually work with Redux by building a simple recipe book application. Chapter 2. In this chapter we will learn how to use it for a simple project.

The code base created in this chapter will be used as the base for all the examples in the rest of this book. It is highly recommended that you follow along with and fully understand this chapter and its code before moving on to more advanced topics. Starter Project Modern client-side applications often require a set of so-called boilerplate in order to make devel- opment easier. The boilerplate may include things such as directory structure, code transformation tools like SCSS and ES compilers, testing infrastructure, and production pipeline tools for tasks such as minification, compression, and concatenation.

To ease the chore of setting up a new project, the open-source community has created dozens of different starter projects. We will use a much simpler boilerplate, just enough to cover all the concepts explained in this book. As our project will be pure Redux, it will require no React or related libraries.

Our project is ready! Time to open the code editor and go over the five files currently making up the project: 1. The former is the list of all the tools needed to build the project. It currently includes only webpack-tools and the Babel transpiler, required to transpile ES The dependencies section lists all the packages we will bundle with our application.

It includes only the redux library itself. In our simple project there is only one settings file larger projects might have more granular files for testing, development, production, etc. Our webpack. In our project every part and page of the application will be rendered starting from index.

It will allow adding recipes and ingredients for each recipe, and will fetch an initial recipe list from a remote server. In accordance with Redux principles, the application will keep all its state in our global store, including some parts of the UI. The first step with any Redux-based app is to plan how data will be arranged in the store. Connecting them to the state will be a bigger challenge.

There are three general approaches to make this connection. We can process both independently. The biggest difference between the second and third options is how the link is made who holds the ID of whom. In the second example, adding an ingredient will require an update in two different parts of the state—in both the recipes and ingredients subtrees—while in the third approach, we can always update only one part of the tree. In our example we will use this method. The subject of state management is covered in detail in the State Management Chapter in Part 2.

Setting Up the Store We will start by creating the store. In Redux there is only one store, which is created and initialized by the createStore method. In our example, the reducer simply returns the same state regardless of the action. To make things more interesting, we can provide a default state to the store. This is useful when learning, but the real use of this feature is mainly with server rendering, where you precalculate the state of the application on the server and then can create the store with the precalculated state on the client.

Adding Recipes To implement adding recipes, we need to find a way to modify our store. As we learned in the previous chapter, store modifications can only be done by reducers in response to actions. This means we need to define an action structure and modify our very lean reducer to support it. Your First Redux Application 29 Actions in Redux are nothing more than plain objects that have a mandatory type property. Our reducers must never change the state, but only create a new copy of it, with any modifications needed.

We are using the Object. To calculate the list of new recipes we use concat instead of push , as push modifies the original array while concat creates a new array containing the original values and the new one. More information about the Object. This, among other reasons, is why in Redux we use the concept of action creators: functions that create the action object for us. Structuring the Code Having all our code in a single file is obviously a bad idea.

After all the changes, the index. As our application grows, more properties will be added to both the recipes and the ingredients subtrees. First, our root reducer is now very simple. All it does is create a new state object by combining the old state and the results of each of the subreducers. Second, our recipes reducer is much simpler as it only has to handle the recipes part of the state. Thus, changes to that part of the tree will only affect the recipes part.

Handling Typos and Duplicates Before moving forward, we need to make one last change to our code to fix something that might not be an apparent problem right now. In large applications this often leads to errors that are very hard to debug, as a typo in the action creator will cause a reducer to ignore an action.

Or, even worse, two developers might use the same string by mistake, which will lead to very strange side effects as unintended reducers will process the dispatched actions. This will catch duplicate names at compile time, even before our code reaches the browser.

One option is to log received actions from the root reducer—but as we will see shortly, this can be problematic. Another option is to use the middleware we discussed in the previous chapter. The store holds a connection to all the middleware and they get actions before the reducers, which means they have access to any actions dispatched to the store.

While this might be a little confusing, it is required by the way Redux combines middlewares in its core. In practice, in the inner most function we have access to the dispatch and getState methods from the store, the current action being processed, and the next method, which allows us to call the next middleware in line.

Our logger prints the current action and then calls next action to pass the action on to the next middleware. In some cases, middleware might suppress actions or change them. That is why implementing a logger in a reducer is not a viable solution: some of the actions might not reach it. In our case, the UI should dispatch an action when it loads to ask Redux to bring data to the store. Since the action requires server access that might take time, our reducer will not be able to handle the response—reducers should return the modified state immediately.

This means we can catch the action in a middleware, submit an Ajax request, and then send a new action to the reducers with the data already inside. This magic is explained in the Reducers Chapter.

We will go into much more detail in the Middleware Chapter. Summary In this chapter we built a simple Redux application that supports multiple reducers, middleware, and action creators. We set up access to a server and built a minimal UI using jQuery.

State Management One of the main strengths of Redux is the separation of state data management from the presentation and logic layers. Due to its division of responsibilities, the design of the state layout can be done separately from the design of the UI and any complex logic flows. The app can manage multiple recipe books, each having multiple recipes. A recipe, in turn, is an object containing a list of ingredients, preparation instructions, images, a favorited flag, etc.

There are two main approaches, one where all the reducers in the chain are aware of the action being passed and one where each reducer only passes the information down to its children. Any changes or additions will require us to check multiple reducers for code changes, thus breaking the encapsulation benefits of multireducer composition and greatly complicating our code. Access to Multiple Nested Data Entities Another problem with the nested state approach is retrieving data.

This approach breaks our separation of concerns model and might require extensive changes to the UI layer s on state structure changes. State as a Database A recommended approach to solve the various issues raised above is to treat the application state as a database of entities.

Any connections between objects e. Nesting levels only affect the parent and children, never the grandparents. The recipes reducer only adds an ID to the array of ingredients, not the whole ingredient object.

Rather, we treat our state as a conventional database from which to extract information for the UI. Keeping a Normalized State While normalized state might seem like a great idea, often the data returned from the server is structured in a deeply nested way. Normalizing the Data With the reducers updated and the action structure defined, we are left with the problem of extracting the payload from the denormalized data we got from the server.

Chapter 3. This will automatically serialize and save our state once it has been modified. Advanced State Sync The redux-persist library has advanced functionality that will allow us to whitelist only part of the state to persist and to specify special serializers for the part of the state that cannot be serialized with JSON. State Management 51 Real-World State In a real-world application, our state will usually contain a number of different entities, including the application data itself preferably normalized and auxiliary data e.

Structure of a Common State Unlike the data coming from the server, some information will be used exclusively by our frontend application for its internal needs.

A common example would be keeping the total number of active server requests in order to know whether to display a spinner. Some of these will come from external libraries like redux-forms, react-redux-router, and others that require their own place in our state.

Keeping the State Manageable To make things as simple as possible, it is best to have a reducer for each key in the base state. This will allow for an encapsulation approach where it is immediately clear who can modify which parts of our state.

Summary In this chapter we discussed the structure of our Redux state and how it should be managed for easier integration with reducers and the UI. In the next chapter we will talk about server communication, the best method of sending and receiving data to and from our server using middleware. Chapter 4. Server Communication Server communication is one of the more important parts of any application.

And while the basic implementation can be done in a few lines of code, it can quickly grow into a complicated mechanism able to handle authentication, caching, error handling, WebSockets, and a myriad of other functionality and edge cases. Online tutorials usually devote little time to this topic, and suggest using regular promises and the redux-thunk middleware to let action creators dispatch actions when data is fetched.

Considering this, we need to be able to both access the store and dispatch asynchronous events—which is the perfect job for a middleware. Before reading this chapter, it is strongly recommended that you read the Middleware Chapter. Server Communication 55 There are a few issues with this code: 1.

Every action creator will need to have the repetitive functionality to handle errors and set headers. Testing gets harder as more async action creators are added. If you want to change the server communication strategy e. Keeping the code as short and stateless as possible, in keeping with the spirit of Redux, is easier when all the action creators are simple functions.

This makes them easier to understand, debug, and test. Luckily, we have the perfect candidate—middleware. As we will see, using this approach we can keep the action creators simple and generate actions that contain all the information needed for a middleware to perform the API request. Our target URL is built from a constant specifying the root e. API Middleware Our goal is to create a generic middleware that can serve any API request and requires only the information passed to it in an action.

It will let any other actions flow down the middleware chain. Handling the return value from the call is a bit more complex, as our middleware needs to figure out what action to dispatch. A simple solution is to pass the next action to be dispatched inside the API action.

To solve this problem, we need to extend our middleware to catch server errors and dispatch events when they happen. Server Communication 59 Loading Indicator Spinner A common question when using Redux is how to show a spinner when server requests are in progress. The middleware approach provides an answer using additional dispatch calls. Before a request starts or after it completes, we can dispatch a special action to be caught by reducers responsible for the UI state. Server Communication 60 Dynamic Action Types Building on the loading indicator example, we might want to handle multiple indicators for different parts of our application, by having multiple subtrees in the ui state sub-tree.

However, this approach is not flexible, encourages code repetition, and forces us to have multiple action types defined for every API action. More Extensions There are still quite a few things missing from our API middleware to make it usable in the real world. We need support for more verbs not just GET , setting of custom headers, timeouts, caching, and more.

Much of this can be done by taking data from the action object or from the store itself. Server Communication 63 Chaining APIs Sometimes fetching data from a server requires a number of different calls—for instance, when the returned data from one is needed to issue additional calls. As we can see, chaining promises is not an ideal solution. When working with Redux we have two other alternatives to use, middleware and sagas.

Using Middleware for Flow In the middleware approach, we split the code handling server access and logic flow. Our API middleware stays the same, and we only need to find another place to put the logic flow.

We can solve this problem by creating a special action flow that has similar behavior to fetchCur- rentUser but also triggers the fetchProfile acton. While it will work, it might cause bugs if we forget to issue the regular setCurrentUser call from our special action handler. This library allows us to build complex asynchronous flow management solutions using sagas and effects. In essence, it uses a special middleware to add a new actor to the Redux world.

The payload can be used to dispatch a fetchProfile action to get the corresponding profile from the server. This is a very basic example of saga usage and does not handle error or allows to cancel requests of flows. Some promise implementations support this feature, but it is also quite doable with the API middleware approach. To allow canceling we need to give a unique ID to each request being sent and keep it for the cancellation phase. Server Communication 69 13 switch action. The setTimeout function is used to clear canceled requests after 5 seconds to prevent the object from filling up needlessly.

With this functionality we can cancel requests at any time and not have to worry about request completion happening long after the user has navigated away from the original location in the app or after a later request has completed for example, two consecutive filter requests for data being sent and the first one returning after the latter one.

Summary In this chapter we have learned how to set up a comprehensive mechanism for server commu- nication. In the next chapter we will cover WebSocket based communication and how well it can work with the Redux architecture. Chapter 5. WebSockets WebSockets have brought a robust socket communication method directly into our browsers. What started as a solution for polling data changes on the server is slowly taking over more and more responsibilities from traditional REST endpoints.

The action-based architecture of Redux makes working with WebSockets exceptionally easy and natural, as it involves using WebSockets as a pipe to pass actions to and from the server.

Basic Architecture WebSockets allow us to open a connection to a server and send or receive messages in a fully asynchronous way. While multiple WebSockets might be used, most applications will require a single one or at most a few connections for different servers based on function chat server, notifications server, etc.

To start, we will build a system to communicate with a single WebSocket, which can later be extended for multi-WebSocket support. Redux Link The general Redux architecture is all about sending well-defined messages to the store. This same scheme can work perfectly for server communication over WebSockets. The server, in turn, can broadcast the message to all other clients. Each will get a perfectly standard Redux action that can be passed directly to their stores. This way our frontend can use Redux actions to pass information between browser windows and machines, using the server as a generic dispatcher.

Our server might do some additional work, like authentication and validation to prevent abuse, but in essence can serve as a message passer. An ideal WebSocket implementation for Redux would allow us to dispatch actions and have them smartly routed to the server when needed, and have any actions coming from the WebSocket be dispatched directly to the store. Code Implementation As with any infrastructure-related code, middleware is the perfect place for our WebSocket implementation.

It will allow us to catch any actions that are required to be sent over the WebSocket and dispatch anything coming from the server.

WebSockets 72 Using Object. WebSockets 73 Handling onopen 1 websocket. In this example we will stop at a generic console. WebSockets 74 Handling onmessage 1 websocket. WebSockets have a readyState property that returns the current socket status.

The standard way to provide special information about actions to middleware is to use the meta key inside an action. Since we are sending the whole action to the server, it might in turn broadcast it to all other clients even ourselves. A Redux-aware server should consider stripping all meta information for any action it receives. To allow the server to authenticate a WebSocket, a special - agreed upon action - needs to be sent by the client.

In the case of Redux, a special action object can be serialized and sent before doing any other work over WebSockets. WebSockets 79 Authentication code in the WebSocket middleware 1 if action. WebSockets 80 When the token is already present in cookie it will be passed to WebSocket as soon as the socket is openned. This might cause problems if the login process happens after the application loads.

Or even worse, when the user logs out our WebSocket might still stay authenticated. It is better to use the action based authentication approach described above to avoid these and similar issues. Summary This chapter has illustrated how well WebSockets work with Redux and the practical steps needed to set up WebSocket-based communication. In the next chapter we will cover the subject of testing and how each part of our Redux application can be tested separately and together.

Chapter 6. Tests One of the key strengths of Redux is its ease of testability. To fully automate the testing suite, we can create unit tests for each of the different actors reducers, action creators, and middleware and combine them together for comprehensive integration tests.

There are a large number of testing tools available, but the exact tooling is less important as most parts of our Redux application will rely on plain JavaScript functions and objects with no complicated libraries or async flows to test. Using other frameworks and tools such as Karma, Mocha, and so on should look very similar to the examples in this chapter. Test Files and Directories To start off we need a way to organize our tests.

There are two main approaches: putting the tests together in the same directory with the implementation files, or putting them in a separate directory. In this guide we will use the latter. The choice is a matter of convenience and personal preference, with the only side effects being different test runner configurations.

We will create a separate test file for each implementation file in our project. Test File Structure In our test files we will use a describe function to wrap all our tests. Redux in Action. Download e-Book. Posted on. Page Count. Marc Garreau, Will Faurot,. Download e-Book Pdf.



0コメント

  • 1000 / 1000