Translator: the Legendary

The original link

Photo by Franco Folini

I’ve been using React for over a year now. I’m also doing training to help people learn Redux from the ground up. I noticed that I explained some of the same concepts over and over again in every practice. I think these concepts are essential if you want to “talk about React.” If you are in the middle of learning, you may be interested in reading this article.

1) It is not a framework

Angular or Ember are frameworks that have helped you make some decisions. React is just a library, and you need to make all the decisions yourself. It focuses on helping you build user interfaces using components.

It doesn’t help you communicate with the server, translate, route, etc. Some people think this is a weakness. A wise man once said:

“Frameworks solve the problem of their creators” — one of my mentors

React is thin, and it’s easy to mix with other third-party libraries. The rich JS ecosystem has a library for everything. You can choose the one you like best and plug it in without being constrained by the design of the frame.

There is, of course, famous JS Fatigue. If you think this is the case and don’t want to make every decision yourself, do a 30-minute study, choose an Opinionated starter Kits/Boilerplates, change whatever you want and just use it.

2) JSX

When you look at the React example, you’ve probably already seen JSX. But React code can also be written in pure JS code:

const rootElement =
  React.createElement('div', {},
    React.createElement('h1', {style: {color: 'red'}}, 'The world is yours'),
    React.createElement('p', {}, 'Say hello to my little friend')
  )

ReactDOM.render(rootElement, document.getElementById('app'))

Copy the code

Some people don’t like to write the entire markup code as a function call. That’s probably why people on Facebook came up with JSX – a “React. CreateElement (Component, props,… Children’s grammatical sugar method “. That’s why we can refactor the above example:

const RootElement = (
  <div>
    <h1 style=>The world is yours</h1>
    <p>Say hello to my little friend</p>
  </div>
)

ReactDOM.render(RootElement, document.getElementById('app'))

Copy the code

Babel converts markup to pure JS code during the build process.

3) this is JavaScript

To generate tokens dynamically in React, you can also use JS:

<select value={this.state.value} onChange={this.handleChange}>
  {somearray.map(element => <option value={element.value}>{element.text}</option>)}
</select>

Copy the code

In the example above, the SomeArray array is mapped to the list of

Although there is no need to use it:

<select onChange={this.handleChange}>
  {somearray.map(element => (
      <option
        value={element.value}
        selected={this.state.value === element.value}
      >
        {element.text}
      </option>
    ))}
</select>

Copy the code

Many popular frameworks use template languages to do this. Each framework has its own template language. So every time you want to use a framework, you need to learn a new template language and its quirks and shortcomings.

The above code comes with a warning about the missing key attribute. Want to know why and how to solve the access [here] (facebook. Making. IO/react/docs /…

I remember the first time I used Control in Angular 1. There is a special ngOptions directive that will generate all possible options for you.

<select
  ng-model=""selectedItem""
  ng-options=""item as item.name for item in items"">
</select>

Copy the code

So far I don’t know what item as item.name for item means.

There are people smarter than me who have memorized how to use various template languages. I often switch from the back end to the front end. For a long time, I didn’t do the front end at all. If you don’t use it, knowledge disappears. That’s why memory doesn’t work for me. But I’m familiar with the map () function and HTML, so the React approach appeals to me.

Another benefit is that static code analysis is free. It is easier to detect JS than custom template tags.

For me, templates are developed based on strings. There are no strict hints. Just some in HTML, not checked in any way. JSX adds more things to JS and makes it more powerful. This is why I disagree when people call JSX a template language.

4) It is declarative

In React, you can write components declaratively. Let’s use

<select value={this.state.value} onChange={this.handleChange}>
  {somearray.map(element => <option value={element.value}>{element.text}</option>)}
</select>

Copy the code

In this
example, you don’t use a for loop to manually create a collection of maps. You’re not saying what it should do, but what it should look like.

5) Separate concerns

In React, you usually keep HTML, JS, and CSS as a component. If you want to display a Row on the grid, you create a Row component and put the HTML, logic, and behavior in a file.

Over the years, we’ve split JS, HTML and CSS into separate files. Pete Hunt calls separation technology. It should not be confused with the concept of separation of concerns.

I often get questions about whether I think this “lack of separation” is strange. But it seems strange to me that people often give examples to defend the strategy of keeping HTML and JS separate:

“If you keep the HTML and JS in separate files, you can easily replace the HTML and keep the JS intact.

If you think about it, it doesn’t work. Most changes to the HTML structure require refactoring of THE JS logic.

“Display logic and markup are unavoidably tightly coupled” — Pete Hunt

If you change the text input to a check box, you need to rewrite the logic.

6) Data transfer

In React, data is passed down the tree of components. To pass data from a parent component to a child component, you need to use props. From a JSX perspective, props is an HTML attribute.

The parent component:

<div>
  <Greetings color={red} text='Hello' />
</div>

Copy the code

In the child component, props is available under this.props.

Child components:

const Greetings = React.createClass({
  render () {
    const {color, text} = this.props
    const divStyle = {padding: 10, backgroundColor: 'black'}
    const headingStyle = {color: color}

    return (
      <div style={divStyle}>
        <h1 style={headingStyle}>{text}</h1>
      </div>
    )
  }
})

Copy the code

7) State

So far, we’ve only talked about static components and static data passing to the component tree. Typically, you want to create a stateful component where the state changes over time. Let’s consider a component that you can enter into this article and display below.

const InputBox = React.createClass({
  getInitialState () {
    return {
      text: ''
    }
  },

  changeText (event) {
    this.setState({text: event.target.value})
  },

  render () {
    return (
      <div>
        <input type='text' onChange={this.changeText} placeholder='text' value={this.state.text} />
        <span>{this.state.text}</span>
      </div>
    )
  }
})

Copy the code

At the beginning, you set the default state of the component. In this case, we want to have an empty text value. To do this, you use the component method getInitialState (), which must return a component’s state object.

To update the status, the event handler changeText () is assigned to the onChange event. To update the state React expects you to use the built-in setState () method.

The component state will be re-rendered once it has been updated. The setState () call is needed to notify React about pending state changes so that it can apply the changes. If something changes, there is no loop of any kind.

You need to remember that setState () is asynchronous. The results will not take effect immediately. The following example shows both the bad and good ways to access state immediately after applying changes:

// Error: //... SomeFunction (value) {this.setstate ({someValue: value}) // May not change console.log('New value: ', this.state.someValue) } // ...Copy the code
// Good: //... SomeFunction (value) {this.setState({someValue: value}, () => {// do something with the New state console.log('New value: ', this.state.someValue) }) } // ...Copy the code

Okay, but what if you need to propagate state changes to the parent component?

8) Incidents rise

Let’s say we have a Parent component that needs to get data from the InputBox child of the previous example.

const Parent = React.createClass({
  gimmeThatState (textFromInput) {
    console.log(textFromInput)
    // or this.setState({text: textFromInput})
  },

  render () {
    <InputBox pushChangesUp={this.gimmeThatState} />
  }
})

Copy the code

The Parent component passes a function (as a prop) so that InputBox can be used to push some data.

The changed InputBox might look something like this:

const InputBox = React.createClass({
  propTypes: {
    pushChangesUp: React.PropTypes.func.isRequired
  },

  getInitialState () {
    return {
      text: ''
    }
  },

  changeText (event) {
    this.setState({text: event.target.value})
  },

  pushChangesUp () {
    this.props.pushChangesUp(this.state.text)
  }

  render () {
    return (
      <div>
        <input type='text' onChange={this.changeText} placeholder='text' value={this.state.text} />
        <span>{this.state.text}</span>
        <button onClick={this.pushChangesUp}>Push changes up</button>
      </div>
    )
  }
})

Copy the code

The first thing you’ll see is a propTypes property at the beginning of the component declaration. It is used to validate properties. To me, it acts like an interface in OOP. By looking at propTypes I immediately know what properties I need to provide to the component to make it work.

Next, the local pushChangesUp () event handler is assigned to the onClick event on the button. When clicked, this function uses pushChangesUp () to push data from props.

The Parent component can now save data to its own state and pass it to different components.

9) How does rendering work

Each call to the setState () method notifies React that the state has changed. React then calls the Render () method to update the in-memory component presentation content (the Virtual DOM) and compare it to what is rendered in the browser. React updates the DOM as little as possible if there are changes.

The child components know they need to rerender because their props have changed.

I often use the diff mechanism on Git as an analogy to this concept. With a snapshot of the two component trees, React compares and then simply exchanges what needs to be exchanged.

I was looking for a clever diagram to describe the render flow, but couldn’t find it. But you can read more about this concept here.

10) Mix is key

A parent component that has state is often called a container component. They are responsible for state management and (as strange as it sounds) rendering child components. The child component is used to trigger event handlers passed from the parent class (such as the InputBox component in the previous example) and display data. The subcomponents responsible for displaying data are called presentation components.

Container components are typically responsible for fetching data, API calls (see componentDidMount() lifecycle methods), and so on. You should keep it in one place to avoid showing side effects in components. Container components should be as oblivious as possible, rather than displaying data.

This separation of concerns and terminology is popularized by Dan Abramov, author of Redux. You can read more in his article.

You can see that it all fits together. When each component part follows a single responsibility, it can be reused with other components.

The biggest challenge is figuring out how to divide these responsibilities and where to place the status. If you want to know more about this topic, search for “Thinking in React” articles.

11) Keep state small

In my training, there are often exercises that involve some kind of list filtering. Suppose you have a list of Todos:

const initialState = [ {id: 1, text: 'laundry'}, {id: 2, text: 'shopping'} // ... ]  const List = React.createClass({ getInitialState () { return { todos: initialState } }, render () { return ( <div> <ul> {this.state.todos.map(todo => <li key={todo.id}>{todo.text}</li>)} </ul> </div> ) } })Copy the code

Now you will add a search box. 50% of people will adopt this method of variation:

const initialState = [ {id: 1, text: 'laundry'}, {id: 2, text: 'shopping'} // ... ]  const List = React.createClass({ getInitialState () { return { todos: initialState, filteredTodos: null } }, search (searchText) { const filteredTodos = this.state.todos(todo => todo.text.indexOf(searchText) > 0) this.setState({filteredTodos: filteredTodos}) }, render () { const {filteredTodos, todos} = this.state // get todos from state const list = filteredTodos === null ? todos : filteredTodos // if there are filtered todos use them return ( <div> <SearchBox onChange={this.search} /> <ul> {list.map(todo => <li key={todo.id}>{todo.text}</li>)} </ul> </div> ) } })Copy the code

You can see here is the state of repetition, two sources of truth and an introduction to spaghetti code. Imagine that you want to update a to-do list and enable search filters.

What’s better? Keep the state as small as possible. If something can be calculated on the fly, then it should be.

There’s a better way to do this:

const initialState = [ {id: 1, text: 'laundry'}, {id: 2, text: 'shopping'} // ... ]  const List = React.createClass({ getInitialState () { return { todos: initialState, searchText: null } }, search (searchText) { this.setState({searchText: searchText}) }, filter (todos) { if (! this.state.searchText) { return todos } return todos.filter(todo => todo.text.indexOf(this.state.searchText) > 0) }, render () { return ( <div> <SearchBox onChange={this.search} /> <ul> {this.filter(list).map(todo => <li key={todo.id}>{todo.text}</li>)} </ul> </div> ) } })Copy the code

Here you only keep searchText to filter the list before rendering. A cleaner approach, a smaller state and no repetition.

12) Conditional rendering

In the previous example, the list was rendered according to some conditional logic. If some criteria are met, you usually need to render part of the tag, and if not, you need to render another part. There are several ways to do this in React.

Ternary operator

In JSX, you can use ternary operators to handle conditional rendering:

React.createClass({
  getInitialState () {
    return {
      hideTodos: true
    }
  },

  render () {
    return (
      <div>
      {
        hideTodos ? 'Sorry there is no data' : <TodoList />
      }
      </div>
    )
  }
})

Copy the code

Possible changes:

  • A ternary operator other than a return expression

  • An if/else block outside of the return expression

Helper method

React.createClass({
  getInitialState () {
    return {
      hideTodos: true
    }
  },

  renderTodos () {
    if (this.state.hideTodos) {
      return 'Sorry there is no data'
    }

    return <TodoList />
  }

  render () {
    return (
      <div>
      {
        this.renderTodos()
      }
      </div>
    )
  }
})

Copy the code

This is a useful method, but when the component is larger, you need to jump up and down between the helper method and the Render () method.

A component

Because a feature switch works so well, this is probably the simplest way to do it. ?????

React.createClass({ getInitialState () { return { hideTodos: true } }, render () { return ( <div> <HideIf condition={this.state.hideTodos}> <TodoList /> </HideIf> </div> ) } }) const HideIf =  React.createClass({ render () { if (this.props.condition) { return <span>'Sorry there is no data'</span> } return this.props.children // children is what's inside <HideIf> element } })Copy the code

13) You don’t need Flux

Probably the most common misconception among React newcomers is that you need to use in conjunction with Redux or some other Flux implementation.

Redux is good. It is the most popular Flux implementation, and offers a great deal of functionality and a concise, practical, testable method, thanks to the great tutorial. But [you probably don’t need it] (medium.com/dan_abramo…

If you’re learning React, if your application is small, if you don’t need global state, or you don’t have any issues that need to track changes in application state — don’t use it. If you want to know more, read here.

conclusion

So, here’s a list of React concepts THAT I talk to people about the most. I highly recommend reading React Docs as it is the best source of knowledge from start to finish. I also recommend watching early React videos (from 2013 to 2014) that describe the problems Facebook was trying to solve when creating React. It will help you realize if you are having similar problems React will help you or should you stick with some other techniques.