React from getting started to **? In my 17 years of working with the front end, I have always used Vue. Every team I joined was Vue, avoiding React perfectly. I know that once I saw Sasuke using ama-tian, AS if I saw React, I turned off Oruto and silently opened React……

The Core Checklist for getting started with React is given directly 👇

The basic use Advanced features
1. Basic use of JSX 1. Uncontrolled components
2. Conditional and list rendering 2.React Portals
3. The event event 3.React Context
4. Controlled components 4. Asynchronous components
5. Parent and child component communication 5. Life cycle SCU
6.setState 6. High-level component HOC
7. Life cycle

React Essential Checklist!! Learn React and tap React to help get started quickly. 👉 in addition, want to learn Vue source friends, click on the portal into the column to see ha ~

First, basic use

1. Basic use of JSX

Case code:

class MyComponent extends React.Component{
  constructor(props) {
    super(props)
    this.state = {
      text: 'Template interpolation'.imageUrl: 'xxx.png'}}render() {
    const myStyle = { color: 'blue' }
    return (
      <div>
        <! -- Template interpolation -->
        <p>{this.state.text}</p>
        <! - - - >
        <img src={this.state.imageUrl} alt=""/>
        <! - the name of the class -- -- >
        <p className="text">{this.state.text}</p>
        <! - style -- -- >
        <p style={myStyle}>{this.state.text}</p>
        <! -- Native HTML -->
        <p dangerouslySetInnerHTML={{ __html: '<i>I wrote it in italics</i>' }} />
      </div>); }}Copy the code
  1. The interpolation{}. Corresponding to the Vue{{}}grammar
    • Used in templates.<p>{this.state.text}</p>
    • Property.<img src={this.state.imageUrl} alt=""/>
  2. The className. Vue writes classes directly and uses V-bind for dynamic class names
    • Class is written as className (since class isReserved word of js).<p className="text">{this.state.text}</p>
  3. Style. Corresponds to Vue’s V-bind
    • Use objects.<p style={myStyle}>{this.state.text}</p>
    • I’ll just inline it.<p style={{ color: 'blue' }}>{this.state.text}</p>
  4. The original HTML. Corresponding to Vue v-HTML
    • <p dangerouslySetInnerHTML={{ __html: '<i>123</i>' }} />

2. Conditional and list rendering

  1. Conditional rendering. Corresponding to the Vuev-if
    // React
    render () {
      return this.state.flag ? <p>is flag</p> : <p>not flag</p>
    }
    // Vue
    <p v-if="flag">is flag</p>
    <p v-else>not flag</p>
    Copy the code
  2. List rendering (The map function,key). Corresponding to the Vuev-for
    // React
    state = {
      list: ['list1'.'list2']
    }
    render () {
      // In {function body}, the map returns a list of Li's
      return (
        <ul>
          { this.state.list.map(item => <li key={item}>{item}</li>)}</ul>)}// Vue
    <ul>
      <li v-for="item in list" :key="item">{{ item }}</li>
    </ul>
    Copy the code

Here we can see that the two are really similar, but:

  • React provides a simple JSX syntax that requires JS capabilities to implement. There is no instruction provided internally, which is understood as simple and easy to use.
  • Vue provides many instructions, such as V-if and V-for. Before using it, you need to understand the relevant usage of the command, which will be convenient for daily use

3. The event – the event

Event notation: onXxxx, such as onClick. In Vue, @click, V-on :click

  1. This when the event calls the method

    • bind(this)
    • Arrow function
    class MyComponent extends React.Component{
      constructor(props) {
        super(props)
        this.state = {
          text: 'Template interpolation'
        }
        // bind(this)
        this.handleClick = this.handleClick.bind(this)
      }
      handleClick = function () {
        this.setState({
          text: 'modify text'})}// Arrow function
      handleArrowClick = () = > {
        this.setState({
          text: 'Modify text from handleStaticClick'})}render() {
        return (
          <div>
            <p>{this.state.text}</p>
            <! Bind (this) can also be written here, but constructor is better -->
            <button onClick={this.handleClick}>change</button>
            <! Static methods are used here. Static method this always points to the instance -->
            <button onClick={this.handleArrowClick}>change</button>
          </div>)}}Copy the code
    • React events are not actually bound to the DOM. And the event invocation does not take place at the component layer, but at the outermost event listener (event delegate). The js this keyword is determined at runtime, binding to the execution environment only when the function is called. So we need to bind this to the event; Or use arrow function notation (bind this to the current component when defining)
  2. The event parameter. (Vue events are native events)

    • Events are not native events, but composite events encapsulated by React. The following code and output:
    handleClick = function (event) {
      // React synthesizes events
      console.log('reactEvent', event)
      // Native events
      console.log('nativeEvent', event.nativeEvent)
    }
    Copy the code

    • All the capabilities of DOM are simulated. Such asevent.preventDefault(),event.stopPropagation()
    • All events are bound todocumentOn (before React17)
    • All events are bound toThe root component(React17) :

  3. Pass custom parameters

    • Normal transfer can be used,eventParameters will beAppend to the last digit
    handleClick = function (param, event) {
      console.log(param, event)
    }
    Copy the code

4. Controlled components

  • Controlled component, state drives view rendering(Corresponding to advanced featuresUncontrolled componentTo understand). As in the formTwo-way binding. Corresponding to the Vuev-model
    class MyComponent extends React.Component{
      constructor(props) {
        super(props)
        this.state = {
          inputVal: 'input'}}render() {
        return (
          <div>
            <p>{this.state.inputVal}</p>
            <input type="text" value={this.state.inputVal} onInput={this.handleInput} />
          </div>)}// Data changes need to be implemented manually (one step further than v-Model)
      handleInput = e= > {
        this.setState({
          inputVal: e.target.value
        })
      }
    }
    Copy the code

5. Parent and child component communication

  1. Transmit and receive data. The corresponding Vue is v-bind and props
  • Passing data:<ChildComponent count={this.state.count} />
  • Received data:
    class ChildComponent extends React.Component {
      constructor(props) {
        super(props)
      }
      render() {
        return <div>
          {this.props.count}
        </div>}}Copy the code
  1. Transfer function. Corresponding to the Vue@xxx=xxx,this.$emit('xxx')
    / / the parent component
    class MyComponent extends React.Component{
      constructor(props) {
        super(props)
        this.state = {
          count: 99}}render() {
        return (
          <div>
            <ChildComponent count={this.state.count} changeCount={this.changeCount} />
          </div>)}// Accept the count passed by the child component to modify its own count
      changeCount = count= > {
        this.setState({
          count
        })
      }
    }
    / / child component
    class ChildComponent extends React.Component {
      constructor(props) {
        super(props)
      }
      render() {
        return <div>
          {this.props.count}
          <button onClick={this.addCount}>addCount</button>
        </div>
      }
      addCount = () = > {
        // Get the props passed by the parent component
        const { changeCount, count } = this.props
        // Call the parent component's changeCount method
        changeCount(count + 1)}Copy the code

6. setState

  1. Immutable values
  • Class component usagesetStateModify the value, be carefulImmutable valuesThe concept of
    // Modify the base type data
    this.setState({
      // Do not directly manipulate the value of state (this.state.count++).
      // this.state.count + 1 is a new result ✅
      // this.state.count++ directly modifies the value ❌ in this.state
      count: this.state.count + 1
    })
    // Change the reference type -- array
    this.setState({
      // Avoid using push, pop, and other methods to modify the array directly
      list: [...this.state.list, 3].// Add a value
      list2: this.state.list.slice(1) / / interception
    })
    // Change the reference type -- object
    this.setState({
      // Avoid making changes directly on the original object
      obj: {... this.state.obj,name: 'jingboran'}})Copy the code
  • You might encounter it in real developmentDeep objectThe case requires setState, which can be usedimmer,immutableA library of immutable values. I recommend one hereRelated articles”, more detailed.
  1. The setStatesynchronous,asynchronous
    // Using setState directly is asynchronous, where the console does not get the modified value
    this.setState({   
      count: this.state.count + 1
    })
    // Synchronization console can't get the changed value (if you need to get the changed value, you can add a callback in setState)
    console.log(this.state.count) 
    
    // Using setState in setTimeout is synchronized
    setTimeout(() = > {
      this.setState({   
        count: this.state.count + 1
      })
      // The latest results are available here
      console.log(this.state.count)
    })
    
    // setState is also synchronized in custom DOM events
    componentDidMount() {
      // Bind the body click event
      document.body.addEventListener('click'.() = > {
        this.setState({
          count: this.state.count + 1
        })
        // Get the latest results
        console.log(this.state.count)
      })
    }
    Copy the code
  2. Merge execution of setState
  • Merge execution – Passing in objects
    // The result is only incremented by 1.
    this.setState({
      count: this.state.count + 1
    })
    this.setState({
      count: this.state.count + 1
    })   
    Copy the code
  • Do not merge execution — pass functions
    // Add 2 to the result
    this.setState((prevState) = > {
      return {
        count: prevState.count + 1}})this.setState((prevState) = > {
      return {
        count: prevState.count + 1}})Copy the code

7. Life cycle

  • React
    • Constructor similar to VueinitPhase (initLifeCycle,initState……)
    • Render similar to Vue$mountPhase (executionrender– > getVNode -> patchTo the DOM)
    • componentDidMountEquivalent Vuemounted
    • There is one more before Render in the component update phaseshouldComponentUpdate(controls whether the component needs render or not), where you can do some performance tuning

  • Vue

Advanced features

1. Uncontrolled components

  • State does not control view rendering. Data is not controlled by component state and is directly related to the DOM
  • Scenario: DOM must be manipulated and setState cannot be satisfied. Such as the input of thetype=fileSome of the interactions
    class MyComponent extends React.Component{
      constructor(props) {
        super(props)
        this.state = {
          inputText: ' '
        }
        // Get the DOM. Ref of Vue
        this.textInput = React.createRef()
      }
    
      render() {
        return (
          <div>           
            <! The ref in Vue corresponds to the ref in Vue, but Vue passes in a string
            <input type="text" ref={this.textInput} defaultValue={this.state.inputText} />
          </div>
        )
      }
      handleClick = function () {
        // Get the DOM value directly
        console.log(this.textInput.current.value)
      }
    }
    Copy the code

2. React Portals

  • Make the component render outside of the parent component. Corresponding Vue3teleport
    • Scenario: For example, in daily development, the parent component sets the layout of Overflow: Hidden. Some pop-ups and pull-down menus (absolute location) in the component are cut and need to escape from the parent component nesting
    return ReactDOM.createPortal(
      <div>
        <p>The child component hangs in the body layer, escaping the parent component</p>
      </div>.document.body
    )
    Copy the code

3. React Context

  • Two core: 1. Data creationprovider; 2. Data consumptionconsumer
  • With transparent data transmission capability, descendant components can access the outermost component data. Kind of like Vuev-bind="$attrs"
    / / MyContext file
    import { createContext } from 'react'
    export default createContext()
    
    // External component Provider
    import MyContext from './MyContext'
    
    class MyComponent extends React.Component{
      constructor(props) {
        super(props)
        this.state = {
          val: 'providerVal'}}render() {
        return (
          // Set value
          <MyContext.Provider value={this.state.val}>
            <div>
              <! -- Second subcomponent -->
              <Second />
            </div>
          </MyContext.Provider>)}}// Consumer -- Class Component
    import MyContext from './MyContext'
    import Third from './Third'
    
    export default class Second extends React.Component {
      // Receive MyContext with the static contextType attribute
      static contextType = MyContext
      // Access this. Context
      render() {
        return (
          <div>
            { this.context }
            <! -- Subcomponent of the Second component -->
            <Third/>
          </div>)}}// Consumer -- function Component
    import MyContext from './MyContext'
    import {useContext} from 'react'
    
    export default function Third () {
      // Use useContext
      const context = useContext(MyContext)
      return (
        <div>{ context }</div>)}Copy the code

4. Asynchronous components

  • Two cores lazy+Suspense. Similar to Vue’s asynchronous components. We can learn and understand together

    // Asynchronous components in Vue -- factory functions
    Vue.component('async-component'.function (resolve) {
        require(['./async-component'], resolve) 
    })
    // The asynchronous component in Vue -- Promise
    Vue.component(
      'async-component'.() = > import('./async-component'))// React's asynchronous component
    // Lazy receives a Promise and returns a new React component
    const Second = React.lazy(() = > import('./Second'))
    class MyComponent extends React.Component{
      constructor(props) {
        super(props)
        this.state = {
          val: 'providerVal'}}render() {
        return (
          <MyContext.Provider value={this.state.val}>
            <div>
              <! -- Fallback is mandatory (displayed when loading is incomplete), receives a component -->
              <React.Suspense fallback={<div>loading...</div>} ><Second />
              </React.Suspense>
            </div>
          </MyContext.Provider>)}}Copy the code

5. shouldComponentUpdate

  1. Focus on performance optimization. Is a lifecycle in a component update
  2. The default returntrue. You can customize the logic by returning false to the componentPerformance optimization
  3. Basic usage:
    class MyComponent extends React.Component{
      constructor(props) {
        super(props)   
      }
      shouldComponentUpdate (nextProps, nextState, nextContext) {
        console.log(nextState.count, this.state.count)
        if(nextState.count ! = =this.state.count) {
          return true // Allow render, which executes render down
        }
        return false // No render, no render
      }
      render() {
        return. }}Copy the code
  4. Why is SCU lifecycle optimization needed
  • ReactComponent update logic for:The parent component is updated and the child component is updated unconditionally. contrastVueIt has aBig difference. Those familiar with the Vue responsive principle know that Vue data is collected by the corresponding component of the rendering Watcher, that is, formedA correspondence. Component updates are triggered only if the value of the current component dependency changes.
  • The following code. The parent component is modified by clicking the buttoncountValue triggers parent component updates. If not setSCU, parent component updates result in child componentsShowTextThe update. Observe that the child component receivespropsHas not been modified and does not need to be rerendered. So the SCU optimization scenario appears ~
    / / the parent component
    class MyComponent extends React.Component{
      constructor(props) {
        super(props)
        this.state = {
          count: 0.text: 'children Component'}}render() {
        return (
          <div>
              <p>{this.state.count}</p>
              <button onClick={this.handleClick}>add count</button>
              <! -- Notice that the text received by the child component has not changed -->
              <ShowCount count={this.state.text} />
            </div>
        )
      }
      handleClick = function () {
        // Parent component click modify Count
        this.setState({
          count: this.state.count + 1}}})/ / child component
    class ShowText extends React.Component{
      constructor(props) {
        super(props)
      }
      componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('is update')
      }
      shouldComponentUpdate (nextProps, nextState, nextContext) {
        // Check whether the text of props is changed
        if(nextProps.text ! = =this.props.text) {
          return true // Allow render, which executes render down
        }
        return false // No render, no render
      }
      render() {
        return (
          <div>
            <p>{this.props.text}</p>
          </div>); }}Copy the code
  • Ponder: Why doesn’t React implement SCU internally instead of providing a lifecycle for developers to implement themselves?
    1. Not all scenarios require performance tuning. It is often a reasonable development pattern to optimize when there is a lag. In all cases, if the depth comparison is done directly on the SCU, this will cause performance loss and is often unnecessary
    2. SCU must be used in conjunction with immutable values. If you implement it internallySCUDepth ratiostateThen determine whether to update the component, and failure to follow the immutable value writing method may cause component update failure. Because there is no rule out non-complianceImmutable valuesDeveloper of the writing method. Such asthis.state.list.push(3)And then writethis.setState({list: this.state.list})This kind of situation
  1. PurComponent— Implements shallow comparison SCU
    • There is a shallow comparison between the props and state in the SCU
    • Using the above case to transform, can achieve the same effect. The parent component changes count and the child component does not perform the update
    // Usage: extends react.pureComponent
    export default class ShowText extends React.PureComponent{
      constructor(props) {
        super(props)
      }
      componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('is update')}render() {
        return (
          <div>
            <p>{this.props.text}</p>
          </div>); }}Copy the code

6. High-level component HOC

  • Component’s common logic is pulled out. It’s just the idea of a higher-order function. If you feel confused, you can read xiao Di’s other article,Here is a case study of higher-order functions
    1. Receive a component and return a new component. For example, each component needs to have the capability of a counter.
    // Higher-order component functions
    function HOCFactory (Component) {
      // Take a Component argument: Component
      class CountComponent extends React.Component {
        constructor(props) {
          super(props)
          // The count of the common logical counter
          this.state = {
            count: 0}}render() {
          return (
            <div>
              <! Pass through all props and pass count to the component for reuse
              <Component {. this.props} count={this.state.count}/>
              <button onClick={this.handleAdd}>add Count</button>
            </div>
          )
        }
        handleAdd = () = > {
          this.setState({
            count: this.state.count + 1}}})// Returns a new component
      return CountComponent
    }
    
    // Common components
    class NormalComponent extends React.PureComponent{
      constructor(props) {
        super(props)
      }
      render() {
        return (
          <div>
            <! -- Receives count passed by higher-order components and displays -->
            <p>Public counter: {this.props. Count}</p>
            <p>The logic of the component itself...</p>
          </div>); }}export default HOCFactory(ShowText)
    Copy the code

    1. It is used as a normal component, but the common logic has been removed
     import HOCComponent from './ShowText'
    
     class MyComponent extends React.Component{
       constructor(props) {
         super(props)       
       }
    
       render() {
         return (
           <div>
             <HOCComponent text={this.state.text} />
           </div>)}}Copy the code
  • The effect is shown below

  • Vue’s probably HOC also to a ~ in fact, the principle is the same ~
const HOCFactory = Component= > {
  const instance = new Vue({
    // Implement common component logic
    created () {},
    mounted () {},
    data () {},
    // The Component passed in render
    render (h) => h(Component, {
      props: {
        / / incoming props}})})// Return this component instance
  return instance
}
Copy the code

In the end, from the detours I have made in learning React, the most efficient way is to have a comprehensive checklist of knowledge system. If there is no actual combat project, and only on the document, in fact, nothing to learn, even if at that time, once time will not forget. No knowledge system has been formed and the impression is not deep. Learning a new framework is best step by step, according to a certain chapter learning, from the basic usage, advanced usage, principle level gradually in-depth, so that you can firmly grasp!