Last year, I wrote a little book about learning React.js. It turned out to be about 100 pages. This year I’m going to challenge myself to boil it down to one article.

This article won’t cover what React is or why you should learn it. Instead, this is an introduction to the basics of React.js for people who are already familiar with JavaScript and familiar with the basics of the DOM API.

All code examples below are labeled for reference. They are purely examples written to provide concepts. Most of them could have written better.

1: Components are everything about React

React is designed around the concept of reusable components. You define widgets and put them together to form larger components.

All small or small components can be reused, even across different projects.

A React component (in its simplest form) is a simple JavaScript function:



// Example 1
// https://jscomplete.com/repl?j=Sy3QAdKHW
function Button (props) {
  // Returns a DOM element here. For example:
  return <button type="submit">{props.label}</button>;
}
// To render the Button component to the browser
ReactDOM.render(<Button label="Save" />, mountNode)Copy the code

Curly braces for button labels are described below. There’s no need to worry about them now. The ReactDOM will also be explained later, but the Render function is what you need to test this example and the following code examples.

The second argument to reactdom.render is the target DOM element that React will take over and control. In the jsComplete REPL, you can use the mountNode variable.

Some points to note about example 1:

  • Component names start with a capital letter. This is required because we’ll be handling a mix of HTML elements and React elements. Lowercase names are reserved for HTML elements. In fact, go ahead and try naming the React component “button.” ReactDOM will ignore this function and render the normal empty HTML button.
  • Each component receives a list of attributes, just like an HTML element. In React, this list is calledprops. Create functional components that you can name by using any nameprops.
  • In the return of the Button component above, we write strange HTML. This isn’t JavaScript, HTML, or even reac.js. However, it became so popular that it became the default setting in the React application. It’s called JSX, and it’s a JavaScript extension. JSX is a compromise! Go ahead and try any other HTML elements in the above function and see how they are supported (for example, returning a text input element).

2: What the flux is JSX?

Example 1 above can be written in pure react.js, without the need for JSX, as follows:



// Example 2 - React component without JSX
// https://jscomplete.com/repl?j=HyiEwoYB-
function Button (props) {
  return React.createElement(
    "button",
    { type: "submit" },
    props.label
  );
}
// To use Button, you would do something like
ReactDOM.render(
  React.createElement(Button, { label: "Save" }),
  mountNode
);Copy the code

Example 1 above can be written in pure react.js, without the need for JSX, as follows:

The createElement function is a function in the React top-level API. There are 1 out of 7 things you need to learn at this level. You can see how short the ReactApi is.

Much like DOM itself has a document.createElement function to create an element specified by the tag name, React’s createElement function is a higher-level function that does something similar to document.createElement. But it can also be used to create an element that represents the React component. When we use the Button component in Example 2 above, we create a React component.

Unlike Document.createElement, React’s createElement can accept a dynamic argument after the second argument to represent the descendants of the created element. So createElement actually creates a tree.

Here’s an example:



/ Example 3- the React 's createElement method API// https://jscomplete.com/repl?j=r1GNoiFBb
const InputForm = React.createElement(
  "form",
  { target: "_blank", action: "https://google.com/search" },
  React.createElement("div".null."Enter input and click Search"),
  React.createElement("input", { name: "q", className: "input" }),
  React.createElement(Button, { label: "Search"}));// InputForm uses the Button component, so we need that too:
function Button (props) {
  return React.createElement(
    "button",
    { type: "submit" },
    props.label
  );
}
// Then we can use InputForm directly with .render
ReactDOM.render(InputForm, mountNode);Copy the code

A few points to note about the above examples:

  • InputFormNot the React component; It’s just a React element. That’s why we went straight toReactDOM.renderUse it in the call instead of using it<InputForm />.
  • We can nestReact.createElementCall, because it’s all JavaScript.
  • React.createElementThe second argument to the attributes and props can be either null or an empty object when the element does not need attributes and props.
  • We can mix HTML elements with React components. You can think of the HTML element as the built-in React component.
  • The React API tries to be as close to the DOM API as possible, so we use classnames instead of classes for input elements. Secretly, we all hope that the React API will become part of the DOM API itself. Because, you know, there are so many benefits.

The code above is what you learned when you introduced the React library. The browser does not handle any JSX business. However, we humans like to look at HTML and use HTML instead of these createElement calls (imagine building a website using document.createElement, I’m sure you can!). . That’s why JSX exists. Instead of calling the form above with react.createElement, we could write it in syntax very similar to HTML:



// Example 4 - JSX (compare with Example 3)
// https://jscomplete.com/repl?j=SJWy3otHW
const InputForm =
  <form target="_blank" action="https://google.com/search">
    <div>Enter input and click Search</div>
    <input name="q" className="input" />
    <Button label="Search" />
  </form>;
// InputForm "still" uses the Button component, so we need that too.
// Either JSX or normal form would do
function Button (props) {
  // Returns a DOM element here. For example:
  return <button type="submit">{props.label}</button>;
}
// Then we can use InputForm directly with .render
ReactDOM.render(InputForm, mountNode);Copy the code

Note the following about the example above

  • It’s not HTML. For example, we are still using classnames instead of classes.
  • We are still considering the above HTML as JavaScript. Look at the semicolon I added at the end.

What we wrote above (example 4) is JSX. However, the version we execute in the browser is the compiled version of it (example 3). To do this, we need to use the preprocessor to convert the JSX version to the React.CreateElement version.

That’s JSX. This is a compromise that allows us to write our React component in htML-like syntax, which is a good consensus.

The word “Flux” in the title above was chosen as the rhyme (…) But it is also the name of a very popular application architecture that is popular on Facebook. The best-known implementation is Redux.

JSX, by the way, can be used elsewhere on its own. This is not unique to React.

3: You can use JavaScript expressions anywhere in JSX

In the JSX section, you can use any JavaScript expression within a pair of curly braces.



// Example 5 - Using JavaScript expressions in JSX
// https://jscomplete.com/repl?j=SkNN3oYSW
const RandomValue = () => 
  <div>
    { Math.floor(Math.random() * 100)}</div>;
// To use it:
ReactDOM.render(<RandomValue />, mountNode);Copy the code

Any JavaScript expression can be placed inside those curly braces. This is equivalent to the ${} interpolation syntax in JavaScript template text.

This is the only constraint in JSX: only expressions. So, you can’t use regular if statements, but ternary expressions do.

JavaScript variables are also expressions, so when the component receives a list of props (RandomValue components don’t have, props is optional), it can use those props inside curly braces. We did this in the Button component above (example 1).

JavaScript objects are also expressions. Sometimes we use a JavaScript object inside a curly brace, which makes it look like a double curly brace, but it’s really just an object inside a curly brace. One use case is to pass a CSS style object to the style property in React:



// Example 6 - An object passed to the special React style prop
// https://jscomplete.com/repl?j=S1Kw2sFHb
const ErrorDisplay = ({message}) =>
  <div style={ { color: 'red', backgroundColor: 'yellow' } }>
    {message}
  </div>;
// Use it:
ReactDOM.render(
  <ErrorDisplay 
    message="These aren't the droids you're looking for" 
  />,
  mountNode
);Copy the code

Notice how I only resolved message in the props parameter. This is JavaScript. Also note that the style property above is a special property (again, it’s not HTML, it’s closer to the DOM API). We use an object as the value of the style property. The object defines the style, just as we would with JavaScript (because it is).

You can even use the React element in JSX, because this is also an expression. Remember, a React element is a function call:



const MaybeError = ({errorMessage}) =>
  <div>
    {errorMessage && <ErrorDisplay message={errorMessage} />}
  </div>;
  
// The MaybeError component uses the ErrorDisplay component:
const ErrorDisplay = ({message}) =>
  <div style={ { color: 'red', backgroundColor: 'yellow' } }>
    {message}
  </div>;
// Now we can use the MaybeError component:
ReactDOM.render(
  <MaybeError
    errorMessage={Math.random() > 0.5 ? 'Not good' : ' '}
  />,
  mountNode
);Copy the code

The MaybeError component above will only display the ErrorDisplay component if an errorMessage string is passed to it and an empty div. React treats {true}, {false}, {undefined} and {null} as child elements of a valid element that render nothing.

You can also use all JavaScript methods (Map, Reduce, filter, concat, etc.) on collections within JSX. Again, the reason is because they return expressions:



// Example 8 - Using an array map inside {}
// https://jscomplete.com/repl?j=SJ29aiYH-
const Doubler = ({value=[1, 2, 3]}) =>
  <div>
    {value.map(e => e * 2)}
  </div>;
// Use it
ReactDOM.render(<Doubler />, mountNode);Copy the code

Notice how I gave valueprops the default because it’s all Javascript. Also notice that I printed an array expression in div, which works in React. It will place each double value in a text node.

4: You can write the React component using JavaScript classes

Simple functional components are great for simple needs, but sometimes we need more functionality. React supports creating components through JavaScript class syntax. Here is the Button component written using class syntax (in example 1) :



// Example 9 - Creating components using JavaScript classes
// https://jscomplete.com/repl?j=ryjk0iKHb
class Button extends React.Component {
  render() {
    return <button>{this.props.label}</button>; }}// Use it (same syntax)
ReactDOM.render(<Button label="Save" />, mountNode);Copy the code

Class syntax is simple. Define a class that extends the base react.componentclass (another top-level React API to learn). This class defines a unique instance function called render (), which returns a virtual DOM object. Each time we use the Button class-based component above (for example, by executing <Button… />), React instantiates an object from this class-based component and uses it in the DOM tree.

That’s why we used this.props. Label in JSX in the render output above. Because each component gets a special instance property called props, that holds all the values passed to the component at instantiation time.



// Example 10 - Customizing a component instance
// https://jscomplete.com/repl?j=rko7RsKS-
class Button extends React.Component {
  constructor(props) {
    super(props);
    this.id = Date.now();
  }
  render() {
    return <button id={this.id}>{this.props.label}</button>; }}// Use it
ReactDOM.render(<Button label="Save" />, mountNode);Copy the code

We can also define class attribute functions and use them where we want, including in the returned JSX output:



// Example 11 -- Using class properties
// https://jscomplete.com/repl?j=H1YDCoFSb
class Button extends React.Component {
  clickCounter = 0;
handleClick = () => {
    console.log(`Clicked: ${+ +this.clickCounter}`);
  };
  
  render() {
    return (
      <button id={this.id} onClick={this.handleClick}>
        {this.props.label} </button> ); }}// Use it
ReactDOM.render(<Button label="Save" />, mountNode);Copy the code

There are a few things to note about example 11

  • handleClickThe function is written using the new class field syntax in JavaScript. This syntax still belongs tostage-2,, but it is the best choice to access component installation instances (thanks to the arrow feature) for many reasons. However, you need to configure it using a compiler like Babel to understandstage-2, (or class field syntax) to get the code above. The jsComplete REPL has pre-configuration.
  • We also use the same class field syntax defined hereClickCounterInstance variables. This allows us to skip using class constructor calls entirely.
  • When we willhandleClickThe function is specified as specialonClickReact property when we don’t call it. We passed the handleClick function reference. Calling functions inside this property is one of the most common mistakes with React.


// Wrong:
onClick={this.handleClick()}
// Right:
onClick={this.handleClick}Copy the code

5: There are two most important differences between React events

There are two very important differences between the way events are handled in the React element and the DOM API:

  • All React element attributes (including events) are named camelCase instead of lowercase. It is aonClickRather thanonclick.
  • We pass an actual JavaScript function reference as an event handler, not a string. It is aonClick = {handleClick}Rather than"OnClick =" handleClick.

Wrap DOM event objects with your own objects to optimize performance for event handling. But in the event handler, we still have access to all the methods available on the DOM event object. React passes wrapped event objects to each handle call. For example, to prevent forms from being submitted by default, you can do the following:



// Example 12 - Working with wrapped events
// https://jscomplete.com/repl?j=HkIhRoKBb
class Form extends React.Component {
  handleSubmit = (event) => {
    event.preventDefault();
    console.log('Form submitted');
  };
  
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <button type="submit">Submit</button> </form> ); }}// Use it
ReactDOM.render(<Form />, mountNode);Copy the code

6: Every React component has a story

The following applies only to class components (components that extend to react.component.component.react.component.react.component.react.component.react.ponent). Function components have a slightly different story.

  1. First, we define a template for React to create elements from components.
  2. We then instruct React to use it somewhere. For example, in the render call of another component, or using reactdom.render.
  3. React then instantiates an element and gives us a set of elements we can usethis.propsAccess to theprops. thosepropsThat’s what we passed in Step 2 above.
  4. Since it’s all JavaScript, the constructor will be called (if it’s already defined). This is the first one: component lifecycle methods.
  5. And then React evaluatesrenderMethod (virtual DOM node).
  6. Since this is the first time React renders elements, React will communicate with the browser (representing our use of the DOM API) to display elements. This process is often referred to as mount.
  7. React then calls another lifecycle method calledcomponentDidMount. We can use this approach to do something, for example, in the DOM that we now know supports processing in the browser. Before this lifecycle approach, the DOM we were dealing with was all virtual.
  8. Some component stories end here. Other components can be unmounted from the browser DOM for a variety of reasons. React calls another lifecycle method before the latter happenscomponentWillUnmount.
  9. The state of any mounted components may change. The parent of the element may be rerendered. In either case, the installed component may receive differentprops. The magic is happening here, and now we need React! Until then, we don’t need to do anything at all
  10. The story of this component continues, but before we do, we need to understand the state I’m talking about.

7: The React component has a private state

The following also applies only to class components. Did anyone mention that some people call presentation only components dumb?

The status-class fields are special fields in any React class component. React monitors the state of each component for changes. But for React to perform these operations effectively, we must change the state field via another React API function we need to learn, this.setState:



// Example 13 - the setState API
// https://jscomplete.com/repl?j=H1fek2KH-
class CounterButton extends React.Component {
  state = {
    clickCounter: 0.currentTimestamp: new Date()}; handleClick =(a)= > {
    this.setState((prevState) = > {
     return { clickCounter: prevState.clickCounter + 1 };
    });
  };
  
  componentDidMount() {
   setInterval((a)= > {
     this.setState({ currentTimestamp: new Date()})},1000);
  }
  
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click</button>
        <p>Clicked: {this.state.clickCounter}</p>
        <p>Time: {this.state.currentTimestamp.toLocaleString()}</p>
      </div>); }}// Use it
ReactDOM.render(<CounterButton />, mountNode);Copy the code

This is the most important example of understanding state. It will complete your basic knowledge of how React interacts. There are a few more little things you need to learn after this example, but from this point of view, it’s mostly you and your JavaScript skills.

Let’s look at example 13, starting with the class field. It has two. The special status field is initialized to an object that contains clickCounter starting with 0 and currentTimestamp starting with new Date().

The second class field is a handleClick function that we pass to the onClick event of the Button element in the Render method. The handleClick method modifies the state of this component instance using setState. Notice that.

We modify the state in the interval timer that starts inside the componentDidMount lifecycle method. It ticks every second and performs a call to this.setState.

In the Render method, we use normal read syntax to read the state properties. There are no special apis.

Now, notice that we updated the status in two different ways:

  1. Pass a function that returns an object. wehandleClickThis is implemented in the function.
  2. By passing a regular object. We implement this in interval callbacks.

Both are acceptable, but when you read and write state at the same time, the first is preferred (as we do). Within the interval callback, we only write to the state, not read it. When in a dilemma, always use the first function argument syntax. It is more secure because setState is actually an asynchronous method.

How do we update our status? We return an object containing the value we want to update. Note that in both calls to setState, we pass only one property from the state field, not both. This is perfectly fine, because setState actually merges what you passed (the return value of a function parameter) with the existing state. Therefore, not specifying the property when calling setState means that we do not want to change the property (rather than remove it).

8:React

React gets its name from the fact that it responds to state changes (though not reactive, but as planned). There is a joke that the reaction should be named Schedule!

However, when the state of any component is updated, what we see with the naked eye is React to the update and automatically reflect the update in the browser DOM (if needed).

Treat the render function input as both

  1. From the parent elementprops
  2. Internal private state that can be updated at any time

As the input to the render function changes, its output may change.

React keeps a record of render history, and when it sees a render different from the previous one, it calculates the difference and effectively translates it into the actual DOM operation performed in the DOM.

9: React is your agent

You can think of React as the agent we hire to communicate with the browser. The current timestamp is displayed as an example. Instead of manually going to the browser and calling DOM API operations to find and update p# timestamp elements every second, we change a property on the component state, and React communicates with the browser on our behalf. I believe this is the real reason for real popularity. We hate browsers (and the many dialects spoken in the DOM language), and React volunteers to do all the talking for us, for free!

10: Every React component has a Story (Part 2)

Now that we know the state of a component, and when that state changes some magic, let’s learn a few final concepts about the process.

  1. A component may need to be rerendered when its state is updated, or when its parent decides that changes are passed to the component’sprops, the component may need to be rerendered
  2. If the latter happens, React calls another lifecycle methodcomponentWillReceiveProps.
  3. If the state object or incomingpropsReact has an important decision to make. Should components be updated in the DOM? That’s why it calls another important lifecycle method here,shouldComponentUpdate. This method is a practical question, so if you need to customize or optimize the rendering process yourself, you must answer this question by returning true or false.
  4. If not specifiedcustomComponentUpdateReact default is a very smart thing to do and is actually good enough in most cases.
  5. First, React calls another lifecycle method at this pointcomponentWillUpdate. React then evaluates the new render output and compares it to the last rendered output.
  6. If the rendered output is exactly the same, React does nothing.
  7. If there are differences, React maps them to the browser.
  8. Anyway, since the update process doesn’t matter (even if the output is exactly the same) React will call the final lifecycle method, rightcomponentDidUpdate.

A lifecycle approach is really a hatch. If you haven’t done anything, you can create whole applications without them. They can be used to very easily analyze what’s happening in your application and further optimize the performance of React updates.

With what you’ve learned above (or some of it, really), you can start creating some interesting React applications. If you’re eager to learn more, visit Plactsight’s React.js primer:

All the Fundamental React.js Concepts, jammed into this single Medium article

Pay attention to my public number, more high-quality articles regularly push