The main content of this chapter

Mutable and Immutable States Stateful and stateless components Components communicate one-way data flows

Chapter 2 gives an overview of React. We spent some time learning React, understanding some of the concepts behind its design and API, and we even walked through how to build a simple comment box with the React component. In Chapter 4, we’ll start using components more fully and start building the Letters Social sample project. But before we do that, we need to learn a little bit more about how we work with the data in React and understand how the data flows through the React application. That’s what this chapter is about.

3.1 Status Introduction

Chapter 2 gives a brief overview of how to handle data in the React component, but we’ll need to spend more time focusing on it if we want to build a large React application. In this section, we will learn:

  • State;
  • React How to handle states;
  • How data flows through components.

Modern Web applications are often built as data-first applications. Granted, there are still many static sites out there (my blog is one of them), but even these sites are constantly updated over time, and static sites are generally considered a different category from modern Web applications. Most Web applications that people use regularly are highly dynamic and full of data that changes over time.

Think of an app like Facebook. As a social network, data is the lifeblood of all useful things, providing multiple ways to interact with other people on the Internet, all by modifying and receiving data on a browser (or other platform). Many other applications contain very complex data to present in the UI that people can understand and easily use. Developers also need to be able to maintain and infer these interfaces and how data flows through them, so the application’s approach to processing data is just as important as its ability to process data over time. The sample application Letters Social, which we’ll start building in the next chapter, uses a lot of variable data, but it’s not as complex as most customer or business applications. We’ll explain it more explicitly in this chapter, and continue learning how to deal with data in React throughout the rest of the book.

3.1.1 What is status

Let’s take a quick look at the state so we can understand it better when we look at the state in React. Even if you’ve never explicitly thought about or heard about “state” in a program before, you’ve probably at least seen it. Most programs may have some corresponding state. If you’ve used front-end frameworks like Vue, Angular, and Ember before, you’ve almost certainly written a UI that has some kind of state. The React component also has state. So what exactly are we talking about when we talk about “states”? Try this definition.

Status All information that is accessible to a program at a particular instant.

This is a simplified definition, one that may overlook some academic nuances, but is sufficient for our purposes. Many scholars have written numerous papers devoted to the precise definition of state in a computer system, but for us, state is information that is accessible to a program in an instant. This includes all the values that can be referenced at any given moment without any additional assignment or evaluation; in other words, it is a snapshot of what is known about a program in an instant.

For example, this might include any variables created previously or other values that are available. When you change a variable (instead of using it to get a value), the state of the program is changed, and it is not the same as before. You can retrieve the state at a given moment just by reading, but as you make certain modifications over time, the state of the program changes. Technically, the underlying state of the machine changes from moment to moment during use, but we only care about the state of the program.

Let’s look at some code and examine the simple program state in Listing 3-1, line by line. Instead of going into all the underlying assignments or processes that happen behind the scenes, we’re just trying to get a clearer picture of the data in the application to make it easier to think about the React component.

Listing 3-1 shows the simple state of the program

const letters = 'Letters'; ⇽-- Save a string in a variable named letters const splitLetters = letters.split(''); ⇽-- Split letters into a string array console.log("Let's spell a word!" ); ⇽-- Print a message splitletters.foreach (letter => console.log(letter)); ⇽-- Print out each letterCopy the code

Listing 3-1 shows a simple script that does some basic assignment and data operations and outputs them to the console. This is tedious, but we can use it to learn more about the state. Javascript uses what is known as run to completion semantics, which means that the program will be executed from top to bottom in the order that would normally be considered. JavaScript engines often optimize code in unexpected ways, but it still behaves in a manner consistent with the original code.

Try reading the code in Listing 3-1 line by line. If you want to use the browser’s debugger execute it, go to https://codesandbox.io/s/n9mvol5x9p. Open your browser’s developer tools, step through each line of code and look at all the variable assignments and other things.

For our purposes, let’s treat each line of code as a point in time. How does the simple definition of state — “all information accessible to an application at a given moment” — describe the state of an application at a given moment? Note that we kept things simple and ignored closures, garbage collection, and so on.

(1) Letters is a variable to which the string “letters” is assigned.

(2) Create splitLetters by splitting each character from letters, letters are still available.

(3) All information from step 1 and Step 2 is available, and a message is sent to the console.

(4) The program traverses each item in the number group and prints out a character. This process can happen several times in an instant, so the information available to array.foreach is also available to the program.

As the program moves forward, the state changes over time, and more information becomes available because no information is deleted and references are not changed. Table 3-1 shows how the available information increases as the program moves forward.

 

Try to walk through your code and think about what information can be used in each line of the program. We tend to simplify our code — and that’s what we’re doing here, because we don’t have to consider every possible dimension at once — but there’s a lot of information available even for simple programs.

One factor we can take seriously is that when running programs become quite complex (just as even the simplest UI tends to become complex), it becomes difficult to reason about them. I mean, the complexity of the system can be hard to remember all at once, and the logic in the system can be hard to think through. This is true of most programs, but it’s particularly difficult when it comes to UI building.

The UI of modern browser applications often represents the intersection of multiple technologies, including server-provided data, style and layout apis, JavaScript frameworks, browser apis, and so on. Advances in the UI framework are aimed at simplifying this problem, but it remains a challenge. As Web applications become more pervasive and integrated into society and everyday life, this challenge tends to increase as people’s expectations of these applications grow. If React is to be useful, it needs to help us reduce or mask the extremely complex state of some modern UIs. Hopefully, you’ll realize React does exactly that. But how? One approach is to provide two specific apis for processing data: properties (props) and state (State).

3.1.2 Variable state and Immutable State

In React applications, there are two main ways to handle state in a component: through states that can be changed and through states that cannot be changed. We’ve simplified it here: There are multiple types of data and state in the application. Data can be represented in many different ways, such as binary trees, maps or sets, or regular JavaScript objects. But the methods for communicating and interacting with states in the React component boil down to these two classes. In React, they are called states (data that can be changed in the component) and properties (data that the component receives and should not be changed by the component).

You’ve probably heard states and properties called mutable and immutable. This is partly true, because JavaScript does not natively support true immutable objects (Symbol may be, but it is beyond the scope of this book). In React components, states are usually mutable, and properties should not be changed. Before diving into the React specific API, let’s delve a little deeper into the idea of variability and immutability.

In Chapter 2, when a state is called mutable, it means that we can overwrite or update the data (for example, variables that can be overwritten). Immutable states, on the other hand, cannot be changed. There are immutable data structures that can only be changed in a controlled way (which is how the state API in React works). You will simulate immutable data structures when you learn about Redux in Chapters 10 and 11.

We can extend the concepts of mutable and immutable slightly to include the corresponding types of data structures.

  • Immutable — an immutable persistent data structure that can support multiple versions over time but cannot be overridden directly; Immutable data structures are usually persistent.
  • Mutable — a mutable temporary data structure that supports only one version over time; Mutable data structures can be overridden as they change and do not support other versions.

Figure 3-1 illustrates these concepts.

 

Figure 3-1 Persistence and temporality in immutable and mutable data structures. Immutable or persistent data structures often record a history and do not change, but version changes over time. However, temporary data structures typically do not record history and are discarded with each update

Another way to think about the difference between immutable and mutable data structures is to consider the different capabilities and memory that each data structure has. Temporary data structures can only hold data for a fraction of a second, while persistent data structures can record changes in data over time. This is where the immutability of immutable data structures becomes clearer: only copies of states are made — they are not replaced. The old state is replaced by the new state, but the data is not replaced. Figure 3-2 shows how the change occurred.

 

Figure 3-2 Processing changes in mutable and immutable data. Temporary data structures have no version, so when you change them, all the previous state disappears. They live in the present, whereas immutable data structures persist over time

Another way to think about immutability and variability is to consider the difference between “save” and “save.” Many computer programs can save the current state of a file or a copy of the current file under a different name. Immutable data is similar to saving a copy when it is saved, whereas mutable data can be overwritten in place.

Although JavaScript itself does not support true immutable data structures, React exposes component state in a mutable way (changing by state) and treats properties as read-only. There is often more to immutable and immutable data structures, but we need not care more about them than we already know about them. If you still want to know more, there are academic studies looking at these issues. Immutable data structures are also widely available in JavaScript applications through libraries such as Immutable JS, but in React we only have to deal with property apis and state apis.

3.2 Status in React

Now we’ve learned more about states and (not) variability. How does all this knowledge fit into React? Well, we learned a little bit about the PROPS API and state API in the previous chapter, so you can expect that they must be an important part of the way components are built. In fact, they are the two main ways React components process data and communicate with each other.

3.2.1 Variable state in React: Component state

Let’s start with the state API. While we can say that all components have some sort of “state” (a general concept), not all components in React have local component state. From now on, when I talk about state, I’m talking about the React API, not the general concept. Components that inherit from the React.componentclass can access the API. React creates and tracks a supporting instance for components created this way. These components also have access to a series of lifecycle methods discussed in the next chapter.

Through this. The state can access those inherited from React.Com ponent of the state of the components. In this case, this refers to an instance of the class, and state is a special property that React tracks. You might think that you can update state by simply assigning it or modifying its properties, but that’s not the case. Let’s look at an example of component state in a simple React component in Listing 3-2. You can create this code on your local machine. Or directly, visit https://codesandbox.io/s/ovxpmn340y.

Listing 3-2 modifies the component state using setState

import React from "react"; import { render } from "react-dom"; Class Secret extends React.Component{⇽-- Create a React component that, over time, It accesses persistent component state -- don't forget to bind class methods to component instances. Constructor (props) {super(props); this.state = { name: 'top secret! ', ⇽- provide an initial state for the component so that attempts to access it in render() do not return undefined or throw an error}; this.onButtonClick = this.onButtonClick.bind(this); ⇽-- Create a React component that accesses persistent component state over time -- don't forget to bind class methods to component instances} onButtonClick() {⇽-- get started with setState, a dedicated API for modifying component state. This function returns a new state object for React to use this.setState(() => ({name: 'Mark'})); } render() { return ( <div> <h1>My name is {this.state.name}</h1> <button onClick={this.onButtonClick}>reveal the secret! </button> ⇽-- bind the function that displays the name to the click event emitted by the button </div>)} render(<Secret/>, Document.getelementbyid ('root') ⇽- rendering the top-level component to the HTML element at the highest level of the application - you can identify the container in various ways, as long as ReactDOM can find it);Copy the code

Listing 3-2 creates a simple component that uses setState to update the component state when a button is clicked to reveal the secret name. Note that setState can be used on this because the component inherits the React.componentclass.

When the button is clicked, the click event is triggered, and functions provided to React in response to the event are executed. When the function executes, it calls the setState method with an object as an argument. This object has a name attribute that points to the string. React will arrange status updates. When updates occur, the React DOM updates the DOM as needed. The render function is called again, but this time with a different value supplied to the JSX expression syntax ({}) containing this.state.name. It shows “Mark” instead of “Top Secret!” My secret identity is blown!

In general, developers want to use setState as sparingly as possible due to performance and complexity (React tracks something for the developer, while the developer mentally tracks another piece of data). Some of the patterns that are so popular in the React community that they allow you to use almost no component state (including Redux, Mobx, Flux, etc.) are worth exploring as an application option — in fact, we’ll cover Redux in Chapters 10 and 11. Although it is often best to use stateless function components or rely on patterns like Redux, using setState itself is not a bad practice — it is still the primary API for modifying data in components.

Before continuing, it is important to never directly modify this.state in the React component. If you try to modify this.state directly, calling setState() later might replace the changes you’ve made. Worse, React doesn’t know about the changes to the state. Even though you can think of component state as something that can be changed, you should still think of this.state as an object that cannot be changed within the component (just like props).

This is also important because setState() does not immediately change this.state. Instead, it creates a pending state transition (the next chapter delves more deeply into rendering and change detection). Therefore, calling this. State after calling the setState method may return an existing value. Because all of this makes debugging situations tricky, only setState() is used to change the component state.

Even with a small interaction like the one in Listing 3-2, a lot of things happen. We’ll continue to break down the various steps that occur when React performs component updates in subsequent chapters, but for now, it’s more important to look more closely at the render method of the component. Note that even if you perform a state change and modify the relevant data, it still happens in a relatively understandable and predictable way.

What’s especially nice is that developers can declare the desired look and structure of components at once. There is no need to do a lot of extra work (showing or not showing highly secret names) for two potentially different states. React handles all the underlying state binding and update processes, and developers just have to say “name should be here”. The nice thing about React is that it doesn’t force you to think about each part of the state at any given moment, as section 3.1.1 does.

Let’s take a closer look at the setState API. It is the primary method of changing dynamic state in the React component, and is often used in applications. Let’s look at the method signature to see what needs to be passed to it:

setState(
  updater,
  [callback]
) -> void
Copy the code

SetState receives a function to set the new state of the component and an optional callback function. The updater function is signed as follows:

(prevState, props) => stateChange
Copy the code

Previous versions of React allowed you to pass an object instead of a function as the first argument to setState. One key difference between the previous version of React and the current version of React (16 and above) is that passing objects implies that setState is inherently synchronous, when what actually happens is that React schedules a change to the state. The signature in callback format conveys this information better and is more in line with React’s fully declarative asynchronous paradigm: It allows the React system to schedule updates in order but not at time. This fits in with a more declarative UI approach, and it’s easier to think about than specifying data updates at different times in an imperative way (often the source of race conditions).

If you need to update the state based on the current state or properties, you can access those states and properties using the prevState and props parameters. This is often useful when you want to implement something like a Boolean switch or when you need to know the last value before performing an update.

Let’s pay more attention to the mechanics of setState. SetState shallow merges the current state with the object returned by the updater function. This means that a developer can generate an object and React will merge its top-level properties into the state. For example, let’s have an object with attributes A and B, where B has some deeply nested attributes and A is just A string (‘ Hi! ‘). Because a shallow merge is performed, only the top-level attributes and the parts they reference are preserved, not every part of B. React does not look for deep-nested properties of B to update. The solution to this problem is to make a copy of the object, update it deeply, and then use the updated object. You can also use a library like immutable.js to make dealing with React data structures easier.

SetState is an intuitive API that provides the ReactClass component with some data that needs to be incorporated into the current state. React handles it for you. If for some reason you need to listen to the completion of a procedure, you can mount it using an optional callback function. Listing 3-3 shows an example of a shallow merge of setState in action. As before, it’s easy to create and run React components using CodeSandbox. This saves you the trouble of setting it up on your own machine.

Listing 3-3 uses setState to shallow merge

import React from "react"; import { render } from "react-dom"; class ShallowMerge extends React.Component { constructor(props) { super(props); This. state = {user: {name: 'Mark', // ⇽-- name exists in the user attribute of the initial state...... colors: { favorite: '', } } }; this.onButtonClick = this.onButtonClick.bind(this); (1) {} onButtonClick enclosing setState ({user: {/ / ⇽ -... Colors: {favorite: 'blue'}}}); colors: {favorite: 'blue'}}); } render() { return ( <div> <h1>My favorite color is {this.state.user.colors.favorite} and my name is {this.state.user.name}</h1> <button onClick={this.onButtonClick}>show the color! </button> </div> ) } } render( <ShallowMerge />, document.getElementById('root') );Copy the code

When learning React, forgetting shallow merges is a common source of problems. In this example, when the button is clicked, the name attribute embedded in the user key in the initial state is overwritten because it is not in the new state. It was intended to keep both states, but one overwrites the other.

Exercise 3-1 Thinking about the setState API

This chapter explores the component API for managing state within the React component. One of the things mentioned is that you need to modify state through the seState API, rather than directly. Why is this a problem and why doesn’t that work? Try https://codesandbox.io/s/j7p824jxnw.

3.2.2 Immutable state in React: properties

We’ve talked about how React handles data in a mutable way with state and setState, but what about immutable data in React? In React, properties (props) are the primary way to pass immutable data, and all components can accept properties (not just components that inherit from React.component.functions) and use them in their constructors, render, and lifecycle methods.

Properties in React are more or less immutable. Libraries and other tools can simulate immutable data structures in components, but the React Props API itself is semi-immutable. If JavaScript’s native object. freeze method is available, React uses it to prevent adding new attributes or removing existing ones. Object.freeze also prevents existing properties (or their enumerability, configurability, and writability) from being modified and prevents prototypes from being modified. This largely prevents modification of the props object, but it is not really technically immutable (although you can think of it that way).

Properties are data passed to the React component, either from the parent component or from the component’s own defaultProps static method. Whereas component state is limited to a single component, properties are usually passed by the parent component. If a developer thinks, “Can I use the state of a parent component to pass properties to children?” Then you’ve got something on your mind. The state of one component can be a property of another component.

Properties are normally passed as properties in JSX, but with React. CreateElement, they can be passed directly to child components through this interface. You can pass any valid JavaScript data as a property to other components, or even components (they’re just classes, after all). Once properties have been passed to the component for use, they cannot be changed within the component. Uncaught TypeError:Cannot assign to read-only property'<myProperty>’ ofObject ‘#<Object>’, or worse, Uncaught TypeError:Cannot assign to read-only property'<myProperty>’ ofObject ‘, or worse The React application will not work as expected because it violates the intended usage.

Listing 3-4 in the next section shows how attributes can be accessed and how not to assign them values. As mentioned earlier, attributes can change over time, but not from within the build. This is part of a single data flow that will be covered in a subsequent section. In short, one-way means changing the data flow from parent to child all the way down. A parent component that uses state (inherited from react.component.com) can change its state, and this changed state can be passed as a property to the child component, changing the property.

Exercise 3-2 Calling setState in the Render method

We have made it clear that setState is the method for updating the state of a component. Where can I call setState? We’ll learn in the next chapter where setState can be called in the component lifecycle, but for now let’s focus on the Render method alone. What happens when setState is called in the render method of a component? Go to https://codesandbox.io/s/48zv2nwqww to do test.

3.2.3 Using Properties: PropTypes and default properties

When using properties, there are apis that can help in the development process: PropTypes and default properties. PropTypes provides type-checking capabilities that you can use to specify what attributes the component is expected to receive. You can specify the data type and even tell the consumer of the component what form of data needs to be supplied (for example, an object with a User attribute that contains a specific key). In previous versions of React, PropTypes was part of the core React library, but it now stands alone as the prop-Types package.

The prop-Types library isn’t magic — it’s a set of functions and properties that help you type your input — and you can easily use it in other libraries to type your input. For example, prop-types could be introduced into another component-driven framework similar to React (such as Preact) and used in a similar way.

To set PropTypes for a component, you need to provide a static property called PropTypes on the class. Note in Listing 3-4 that static property names set on component classes start with lowercase letters, while object names accessed from the prop-types library start with uppercase letters (PropTypes). To specify which property is required by the component, add the property name to validate and assign it a property from the default export of the prop-types library (import PropTypes from ‘prop-types’). You can declare any type, form, and necessity (optional or mandatory) for attributes using PropTypes.

Another tool that can make the development experience easier is default properties. Remember how to use a class’s constructor to provide the initial state of a component? You can do something similar for attributes. You can provide default properties for components through a static property called defaultProps. Using default properties can help ensure that the component has what it needs to run, even if the user forgets to provide properties for it. Listing 3-4 shows an example of using PropTypes and default properties in a component. You can run the code at https://codesandbox.io/ S / 31ML5PMk4m.

Listing 3-4 Immutable properties of the React component

import React from "react"; import { render } from "react-dom"; import PropTypes from "prop-types"; Class Counter extends React.Component {static propTypes = {⇽-- specifies an object describing the "form" incrementBy: PropTypes. Number, onIncrement: PropTypes. Func. IsRequired ⇽ - for any links PropTypes isRequired to ensure that the display in the presence of property without warning}; static defaultProps = { incrementBy: 1 }; constructor(props) { super(props); this.state = { count: 0 }; this.onButtonClick = this.onButtonClick.bind(this); } onButtonClick() { this.setState(function(prevState, props) { return { count: prevState.count + props.incrementBy }; }); } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={this.onButtonClick}>++</button> </div> ); } } render(<Counter incrementBy={1} />, document.getElementById("root"));Copy the code

3.2.4 Stateless function components

What can be done to create a simple component that uses properties only and has no state? This is often the case, especially with some of the common React friendly application architecture patterns we’ll explore later, such as Flux and Redux. In these cases, we usually want to keep the state in a central location rather than scattered across components. But there are other situations where just using attributes can be useful. If React doesn’t have to manage supporting instances, it’s good to reduce the application’s consumption of resources.

As it turns out, you can create a component that uses properties only: a stateless function component. These components are sometimes referred to by developers as stateless components, functional components, and other similar names, which sometimes makes it difficult to follow what is being discussed. They usually refer to the same thing — a component that does not inherit from React.componentand therefore does not have access to component state or other lifecycle methods.

Not surprisingly, stateless feature components are just components that can’t access or use React’s state API (or any other method inherited from React.component.com). It has no state not because it doesn’t have any kind of (generic) state, but because it doesn’t get a supporting instance of React to manage. This means no lifecycle methods (covered in Chapter 4), no component state, and probably less memory.

Stateless function components are functions because they can be written as named functions or anonymous function expressions assigned to variables. They only accept attributes, and they return the same output for a given input, so they are basically considered pure functions. This makes them fast, as React has the potential to be optimized by avoiding unnecessary life cycle checks or memory allocation. Listing 3-5 shows an example of a stateless function component. You can go to https://codesandbox.io/s/l756002969 to run the code.

Listing 3-5 stateless function components

import React from "react"; import { render } from "react-dom"; import PropTypes from "prop-types"; Function Greeting(props) {⇽-- You can use functions or anonymous functions to create a stateless function component return <div>Hello {props. For}! </div>; } the Greeting. PropTypes = {for: propTypes. String. IsRequired ⇽ - for any form of stateless function components, can use a function or variable attribute to specify propTypes and default attribute}; Greeting.defaultProps = { for: 'friend' }; ⇽-- For any form of stateless function component, you can specify propTypes and default render(<Greeting for="Mark" />, mountNode) using properties of functions or variables; // Const Greeting = (props) => <div>Hello {props. For}</div>; // Specify PropTypes and default attributes as before // render(<Greeting name="Mark" />, document.getelementById ("root")); ⇽-- Stateless function components can be created using functions or anonymous functionsCopy the code

Stateless function components are powerful, especially when combined with parent components that have supporting instances. Rather than setting state across multiple components, create a single stateful parent and have the rest use lightweight child components. In Chapters 10 and 11, we’ll use Redux to take this model to a whole new level. React applications that use Redux tend to create fewer stateful components (although there are still cases where stateful components work) and centralize state into a single location (i.e., store).

Exercise 3-3 Using the state of one component to modify the properties of another component

This chapter discusses properties and states, the two main ways to process and pass data in the React component. Never change the state or properties directly. Instead, use setState to tell React to update the component’s state. How can I use the state of one component to modify the properties of another? You can go to https://codesandbox.io/s/38zq71q75 to try.

3.3 Component Communication

When building a simple comment box component, we’ve seen that you can create components from other components. This is one of the reasons React is so great. Developers can easily build other components out of child components, while keeping things nicely bundled together and also easily representing IS-A and HAS-A relationships between components. This means you can think of a component as part of a component or as something specific.

It’s great to be able to mix and match components and build things flexibly, but how do you get them to talk to each other? Many frameworks and libraries provide frame-specific ways for different parts of an application to communicate with each other. In Angular.js or ember.js, you’ve probably heard of or used services to communicate between different parts of your application. Typically these are widely available long-term objects in which a developer can store state and access it from different parts of the application.

Does React use a service or something like that? No. In React, if you want components to talk to each other, you need to pass properties, and when you pass properties, the developers do two simple things:

  • Accessing data (either state or property) in the parent component;
  • Pass data to child components.

The example in Listing 3-6 shows both the familiar parent-child relationship and the ownership relationship. You can go to https://codesandbox.io/s/ pm18mlz8jm running code.

Listing 3-6 passes properties from parent to child components

import React from "react"; import { render } from "react-dom"; import PropTypes from "prop-types"; Const UserProfile => {⇽-- Create a stateless function component that returns a sample image return <img SRC ={' https://*******. *******.com/user/${props.username}`} />; }; Userprofile. propTypes = {pagename: proptypes. string ⇽-- Remember, even on stateless function components, you can still specify default properties and propTypes}; Userprofile. defaultProps = {pagename: "erondu" ⇽-- Remember, even on stateless function components, you can still specify default properties and propTypes}; const UserProfileLink = props => { return <a href={`https://ifelse.io/${props.username}`}>{ props.username}</a>; }; Const UserCard = props => {⇽-- UserCard is the parent of UserProfile and UserProfileLink return (<div> <UserProfile username={props.username} /> <UserProfileLink username={props.username} /> </div> ); }; render(<UserCard username="erondu" />, document.getElementById("root"));Copy the code

3.4 One-way Data Flow

If you’ve developed Web applications using frameworks before, you’re probably familiar with the term two-way data binding. Data binding is the process of establishing connections between the application UI and other data. In practice, this often means connecting application data, such as users, to a library or framework of the user interface and keeping both synchronized. They are synchronized with each other and therefore bound together. A more helpful way to think about React is as a projection: THE UI is the data projected onto the view, and as the data changes, the view changes, as shown in Figure 3-3.

 

Figure 3-3 Data binding usually refers to the process of establishing a connection between application data and a view (the presentation of that data). Another way to think about it is as a projection of data to something the user can see, such as a view

Data flow is another way to think about data binding: how does data flow through different parts of an application? In essence, people ask, “What updates what, from where, and how?” Understanding how the tools you’re using shape, maintain, and move data is extremely important if you want to use them well. Different libraries and frameworks take different approaches to data flow (React doesn’t have a different idea of how to handle data flow).

In React, data flows are one-way. This means that the flow between entities is not horizontal — in which case they can update each other — but rather a hierarchy is established. Data can be passed through components, but without passing properties, you cannot touch and modify the state or properties of other components, nor can you modify data in the parent component.

However, you can send data back up the hierarchy through callback functions. When a parent component receives a callback from a child component, it can modify its data and pass the modified data to the child component. Even in the case of a callback function, the data flows down and is still determined by the parent that passes the data down. This is why we call the data flow in React one-way, as shown in Figure 3-4.

 

Figure 3-4 Data flows in one direction in React. Properties are passed from parent to child (from owner to owner), and the child cannot edit the state or properties of the parent. Each component with a supporting instance can modify its own state but cannot modify anything outside of itself, except to set the properties of its children

One-way data flow is particularly useful when building uIs because it makes it easier to think about the way data flows through an application. It is often easier to predict how data will move through an application, thanks to the hierarchy of components and the way properties and states are limited to components.

It may sound like a good idea to avoid this hierarchy to some extent, and to be able to change whatever you want from any part of the application, but in practice this often leads to an unpolished application and potentially difficult debugging situations. Subsequent chapters will explore architectural patterns such as Flux and Redux, which allow you to coordinate actions across components or applications while maintaining a one-way data flow paradigm.

3.5 summary

The following topics are discussed in this chapter.

  • State is information that is accessible to a program at a particular moment in time.
  • Immutable states don’t change, mutable states do.
  • Persistent, immutable data structures don’t change — they just record their changes and create their own copies.
  • Temporary, mutable data structures are purged during updates.
  • React uses both mutable data (component local state) and pseudo-immutable data (properties).
  • Properties are pseudo immutable and should not be modified once set.
  • Component state is tracked by the supporting instance and can be modified using setState.
  • SetState performs shallow merging of data, updates component state, and preserves any top-level attributes that are not overridden.
  • The data flow in React is one-way, from the parent to the child. Child components send data back to the parent through callback functions, but they cannot directly modify the state of the parent, and the parent cannot directly modify the state of the child. Components interact with components through properties.

Excerpt from React Combat

 

React was designed to help developers deliver an amazing user experience. React is a powerful tool available to every developer! Clever design for managing state, data flow, and rendering is key to success, so that your application runs smoothly and is memorable. By tapping into this extremely rich ecosystem of components and libraries, developers can master the secrets of building Web applications that are enjoyable for both developers and users. This book guides you to think like an expert about user interfaces (UIs) and teaches you how to build them with React. The book is very practical, with many practical examples to get the reader started quickly. The goal of this book is to educate the reader on the core concepts of rendering, lifecycle methods, JSX, data flow, forms, routing, integration with third-party libraries, and testing, and to help the reader use the application design concepts introduced in this book to drive the popularity of applications. As you learn how to integrate React into a full-stack application, you can also explore Redu line state management and server-side rendering, and even get your hands on React Native for mobile UI.