react Reading Notes

Posted by vulcant13 on Sat, 16 May 2020 21:57:03 +0200

Source Digging Booklet - react Actual: Design Patterns and Best Practices

react design idea

  1. Property Expansion - Keep the props required by the current component and pass on other props
  var obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
  const { a, ...other } = obj
  console.log(other)  // {b: 2, c: 3, d: 4, e: 5}
  1. In react, the interface is entirely data driven
  2. In react, everything is a component
  3. props are the basic way of communication between react components
  // You can record user access path operation information, accessing an online resource each time you enter a page or function
  // a.js
  export default Beacon extends React.Component {
    componentDidMount() {
      const beacon = new Image()
      beacon.src = 'https://sxc.image/i.png'
    }
    
    render() {
      return null
    }
  }
  // b.js
  render() {
    <div>
      <Beacon/>
    </div>
  }

  // Code organization optimization - renderXXX function accesses the same props and state, code coupling is severe
  class StopWatch extends React.Component {

    renderClock() {

    }

    renderButtons() {

    }

    renderSplitTimes() {

    }
    
    render() {
      const Clock = this.renderClock()
      const Buttons = this.renderButtons()
      const SplitTimes = this.renderSplitTimes()

      return (
        <div>
          {Clock}
          {Buttons}
          {SplitTimes}
        </div>
      )
    }
  }
  // Better organization
  class StopWatch extends React.Component {
    render() {
      return (
        <div>
          <Clock />
          <Buttons />
          <SplitTimes />
        </div>
      )
    }
  }
  const Clock = (props) = {

  }
  const Buttons = (props) => {

  }
  const SplitTimes = (props) => {

  }

Design react component principles and best practices

1. Keep the interface small and props small
 2. Divide components according to data boundaries and make full use of combinations
 3. Extract the state to the upper component so that the lower component only needs to be implemented as a pure function
 4. Avoid renderXXXX functions
 5. Prefix props of callback function types, such as on or handle - onStart
 6. Use propTypes to define props for components
 7. Try to have individual files for each component
 8. Get properties of parameter props by deconstructing assignments - const {a, B} = {a: 1, b: 2}
9. Use property initialization to define state and member functions - give default value const {data = []} = this.props
  /*
    1. Try not to write inline functions in jsx
    2. New function objects are generated for each rendering
    3. The props (methods, data, status, etc.) passed to the component are new and cannot be checked by shouldComponentUpdate to avoid duplicate rendering
  */
  <Buttons
    activated={this.state.isStarted}
    onStart={() => {/* TODO */}}
    onReset={() => {/* TODO */}}
  />
  /*
    1. style Use of attributes
    2. Inline Styles creates a new style object each time the component renders
    3. If the style does not change, the style object should be extracted outside the component and an object can be reused
  */
  // bad
  const Clock = (props) => {
    return <h1 style={color: '#Ccc'}>Miss Sister looks great <h1/>
  }
  // good
  const style = {
    color: '#ccc'
  }
  const Clock = (props) => {
    return <h1 style={style}>Miss Sister is so beautiful<h1/>
  }

Component Style

1. The same element styles in different components affect each other. Both a.js and b.js have h1 components, and styles influence each other.
2. Add styled-jsx/styled-component support
  // a.js
  index.css
  h1: {
    color: red
  }
  <h1>a</h1>
  // b.js
  <h1>b</h1>
  
  // a.js
  .a h1: {
    color: red
  }
  <div className='a'>
    <h1>a</h1>
  <div/>
  // b.js
  <div className='b'>
    <h1>a</h1>
  <div/>

Split State Component from Stateless Component

1. The Software Design Principle of Separation of Responsibilities means that one module is responsible for as little as possible and each module is focused on one function, which is conducive to code maintenance.
2. Data rendering page in react, UI = f(data), but try to separate the acquisition and management of data from interface rendering, that is, put the logic of acquiring and managing data in the parent component and the logic of rendering interface in the child component
 3. When component A renders component B, even if props are passed in, component B will complete the rendering process once
 4. Functional react components have the advantage of not having to manage state and consuming less resources, but function components cannot use shouldComponentUpdate to optimize reduced rendering
 5. The shouldComponentUpdate implemented in PureComponent makes a shallow comparison of the incoming parameters. When the incoming props are an object, such as {a:1, b:2} => {a:2, b:2}, there may be a case where the UI is not updated
 6. shouldComponentUpdate function, called before rendering render function each time, returns true to continue rendering, returns false to stop immediately, can process deep data
 7. When using PureComponent, try to create all objects, arrays, and functions outside of the render definition, and ensure that no changes are made between calls - refer to the table example
 8. React.memo shallow comparison
  export default class A extends React.Component {
    state = {
      joke: null
    }

    componentDidMount() {
      fetch(url, {header: {'Accept': 'application/json'}})
        .then(res => {
          return res.json()
        })
        .then(json => {
          this.setState({joke: json.joke})
        })
    }

    render() {
      return <B value={this.state.joke} />
    }
  }

  export default class B extends React.Component {
    render() {
      return (
        <div>
          <img src={url} />
          {this.props.value || 'loading...'}
        </div>
      )
    }
  }
  <Table
    // map returns a new array one at a time, shallow comparison fails
    rows={rows.map()}
    // Enumerated objects are always different - try not to write inline styles
    style={{color: '#ccc'}}
    // Arrow functions are re-rendered each time - the component level does not bind events through the arrow function
    onUpdate={() => {}}
  />

Advanced Components

To be added...

render props mode

1. Form of render props
 2. render props are really injection dependent
 3. How to use render props to implement logic between shared components
 4. Dependent Injection: ** When Logical A relies on Logical B, A cannot be universal if A is directly dependent on B.Dependent Injection is the passing of B's logic as a function to A so that only the functional interfaces between A and B need to be agreed upon - Component A and B are not written in Component A, but by passing B as a parameter to Component A**
  // Display different components when the user is logged on and not logged on
  const Auth = (props) => {
    const userName = getUserName()
    if(userName) {
      const allProps = {userName, ...props}
      return (
        <React.Fragment>
          {props.login(allProps)}
        </React.Fragment>
      )
    } else {
      return (
        <React.Fragment>
          {props.noLogin(props)}
        </React.Fragment>
      )
    }
  }

  <Auth
    login={({userName}) => <h1>Hello {userName}</h1>}
    noLogin={() => <h1>Please login</h1>}
  />

Provider Pattern

1. Provider mode, in order to ** resolve cross-level information transfer between components **, A-B-C-D-...-X, when data is transferred from A to X, B-C-D... is passed through props. However, data in props is not needed in B-C-D..., and props transfer errors are prone to occur when components change.
2. The provider model is essentially composed of two roles: one is called provider, the other is consumer, the provider (A) is at the top of the component tree, and the consumer (X) is at the bottom.
3. Implemented through the contextual functionality provided by **react (v16.3.0+), which creates a'context'in which all components can access the same data**
4. Refer to the x2 code in react-app

Composite Components

1. Pattern = Context + Solution
 2. Solve the problem, ** When the parent component wants to pass some information to the child component, but it is cumbersome to pass through props**

Component State

1. UI = f(data), data = props + state, props represent external incoming data, and state represents the internal state of the component
 2. What kind of data can be stored in member variables?
3. If data comes in from outside, place it in props
 4. ** If it is internal component data, should changes to this data immediately cause a component to redraw, if so, in the state, not in the member variable**
5. The state will not be modified synchronously, and if called synchronously during the life cycle of the react or in the processing function, setState will not synchronize the state immediately and repeat rendering, but if setState is triggered by other conditions, this may not be the case-When called in a life cycle or event function, react opens something similar to a tag. While the tag is open, setState calls place tasks in the task queue. When the function call ends, the task queue is batched and the tag is closed
 6. Functional setState - When the first parameter of setState is a function, an executable task function is added to the task list, react updates the state once before it finishes processing a task, and passes the new state to the task function
  // Code 1
  class Foo extends Component {
    foo = 'foo'

    render() {
      return <div>{this.foo}</>
    }
  }
  // Code 2
  this.state = {
    count: 0
  }

  this.setState({count: 1})
  console.log(this.state.count) // 0
  // Code 3
  setTimeout(() => {
    this.setState({count: 2})
    console.log(this.state.count) // 2
  })
  // Code 4 - The result is a value given to this.state.count for all 13 tasks
  this.state = {
    count: 0
  }
  this.setState({count: this.state.count + 1})
  this.setState({count: this.state.count + 1})
  this.setState({count: this.state.count + 1})
  // Code 5 - Functional setState, result 3
  // this.setState((preState, props) => ({})
  function increment(state, props) {
    return {count: state.count + 1}
  }
  this.state = {
    count: 0
  }
  this.setState(increment)
  this.setState(increment)
  this.setState(increment)

redux usage pattern

1. Use scenario-state maintenance for complex applications, similar to a global store, ** and stores can only modify data on stores if they accept certain'actions'. Stores respond to these'events'by modifying the state (function reducer to modify the state)**
2. Event - Response Function - Store
 3. For a state, is it in the store or in the component's own state?
4. See if the state is shared by multiple react components - data sharing among different levels of components
 5. See if this component is mounted again after unmount, and if the previous state needs to be preserved - if the component is destroyed and rendered again, and if the previous input needs to be preserved
 6. Code organization - role-based classification (modal,services,view,action,reducer) and feature-based classification (module classification where features are installed)
7. The connect function takes two parameters, one mapStateToProps maps a state on Store to props, the other mapDispatchToProps maps a props of callback function type to a dispatch action, and the connect function call produces a'higher order component'
8. react-redux uses three pattern-provider patterns, higher-order components, stateful components, and stateless components
  // Code 1
  import { createStore } from 'redux'
  import { Provider } from 'react-redux'
  import store from './store'

  const store = createStore(store)

  <Provider store={store}>
    {Provider All components below can connect To a given store}
  </Provider>
  // Code 2
  const Button = ({count, onIncrement}) => {
    return (
      <div>
        <div>{count}</div>
        <button onClick={onIncrement}>+</button>
      </div>
    )
  }
  // Code 3
  import { connect } from 'react-redux'

  const mapStateToProps = (state) => {
    return {
      count: count + 1
    }
  }

  const mapDispatchToProps = (dispatch) => {
    onIncrement: () => dispatch({type: 'INCREMENT'})
  }

  const Counter = connect(mapStateToProps, mapDispatchToProps)(Button)

mobx usage pattern

To be added...

redux versus mobx modes

To be added...

Routing react router

1. Single-page application - Map URL s to corresponding pages for processing, switch between pages for local updates
 2. Dynamic Route-to-Point routing rules are not predetermined but determined during rendering (React Router v4)
3. Static routing-routing rules are fixed

To be continued

Topics: Javascript React JSON Fragment less