React class components and function components to modify their state design mechanism

The class components

 export default class App extends Component {
  state = {
    list: {
       name:'zhangsan'}};render() {
  
    return (
      <div>.</div>); }}Copy the code

If you want to change the class component’s list status, as shown in the previous code:

    this.setState({list: {name:'lisi} ') // List status {name:'lisi
     }
Copy the code

If you do not want to change the value of the name field, you just want to add a new attribute value to it.

    this.setState({ list: {age:18}})
    
    // The list status is changed to
    {
       name:'lisi, age:18 }Copy the code

Many people wonder why the name attribute still exists when the list is changed to age.

Conclusion: Because the setState of React is used to modify the state of the class component, it is stipulated that the new data will be merged with the original data, rather than replaced

Function component

  • Function components use useState Hook to declare their own state and modify the state of the method function, as follows:
import React, { useState, useEffect, useCallback, useMemo } from "react";
import Header from "./components/Header";
import List from "./components/List";
import Footer from "./components/Footer";
import "./App.css";
import { myContext } from "./context";

export default function App() {

  let arr = [
    {
      id: 1.checked: true.title: "Play"}, {id: 2.checked: false.title: "Look at the beauty."}, {id: 3.checked: true.title: "Sing",},]const [data, setData] = useState(arr);

  // Pass data as value to context.provider
  const contextValue = { data, setData };

  return (
    <myContext.Provider value={ contextValue} >
      <div className="todo-container">
        <div className="todo-wrap">
          <Header ></Header>
          <List></List>
          <Footer></Footer>
        </div>
      </div>
    </myContext.Provider>
  );
}
Copy the code

MyContext is a Context created by react.createcontext (), wrapped in this component with the myContext.provider tag. The value attribute passes a value, and all of the children below get the value passed by value, and all of the children below trigger rerendering as the value inside value changes.

Mycontext. Provider has an input box to add the task component:

import React, {
  useState,
  useEffect,
  useCallback,
  useMemo,
  useContext,
} from "react";
import { nanoid } from "nanoid";
import { myContext } from ".. /.. /context";
import "./index.css";

export default function Header(props) {
  const { } = props
  const [inputV,setInputV] = useState(' ')

  // Get the ancestor component's Context
  const { data,setData } = useContext(myContext);
  console.log("Header data :>> ", data);

  // The input box triggers the modification event
  let changeMethod = useCallback((evt) = > {
    console.log("Header changeMethod :>> ", evt.target.value);
    setInputV(evt.target.value)
  });

  // The input box triggers the event of keyboard key lifting = "Adds data
  let keyUpMethod = useCallback((evt) = > {
    console.log("Header keyUpMethod :>> ", evt.target.value);
    if (evt.keyCode === 13) {
      let tempData = data; // Note here...................
      tempData.unshift({
        id: nanoid(),
        checked: false.title: evt.target.value,
      });
      console.log(`tempData`, tempData);
      setData(tempData);
      setInputV(' ')
      console.log(data); }});return (
    <div className="todo-header">
      <input
        type="text"
        placeholder="Please enter your task name and press Enter to confirm."
        value={ inputV }
        onChange={changeMethod}
        onKeyUp={keyUpMethod}
      />
    </div>
  );
}

Copy the code

There is a keyUpMethod event in the above code block, which will be triggered when the input box keyboard is lifted, and when the lifted key is 13=>Enter, the data value passed by the ancestor component obtained through useContext Hook and the method setData to modify the value will be obtained first. The next step is to declare a temporary variable to get the previous value, append the new data to the front of the array, and then call setData to modify the data. To re-render the following descendant components.

Instead, note the line marked let tempData = data; . The effect is not what we expected, the data is added, and the component is rerendered. Instead, it goes like this:

Using the React debugger, we can see visually that the data array has been added to 6 data items, and the list does not trigger a re-rendering. Note that this is the focus of this article, why?? Is not scientific…

When designing the React Hook, it is required to use the data created by useState. When modifying the React component, it does not merge the original data, but directly replace the original data.

Now that you know how it works. Then we’re not too far from the truth. Let tempData = data; What is? If data is a reference type, we are simply making a shallow copy.

Here’s how shallow copy works:

This code means that tempData gets the address of the reference to data. A new heap is not completely created to hold the previous data. So even if you change the data, you’re only changing the data that was in the original heap. React does not consider this to trigger page rerendering. Change to deep copy can solve this pit!!!!

let tempData = [...data]; / / use... And array destruct assignment can be deep copy array, the corresponding object deep copy is {... data}
// Note:... Extensions can only copy a one-dimensional array or a layer of object deconstruction,
Parse (json.stringify (' reference type variable '))) for deep copy of data
Copy the code

Brothers and sisters, click on the wave to share fun technology!

The Denver nuggets:Juejin. Cn/user / 303430…All original good articles

CSDN:Blog.csdn.net/qq_42753705…All original good articles

Segmentfault think no:Segmentfault.com/u/jasonma19…All original good articles