Development Essay: useRef before obtaining state and useEffect pit small note

16. useEffect the pit and prior to using the recording state useRef

1. Scene Description

Usage Use this useEffect hooks, we will pass a dependent by adding a term to him, to finish when one or some of the changes depend on the operation of some side effects to complete its normal usage is as follows:

import React, { useEffect, useState } from "react";
import "./styles.css";

const Profile = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("Number is added!");
  }, [count]);
    
  return (
    <>
      <p>Current weight: {count}</p>
      <button onClick={() => setCount(count+1)}>+1</button>
    </>
  );
};

export default Profile;

However, when the scenario became more complex, so we found two problems :

  • When the dependency is a reference type variable (array), regardless of whether or not to rely change, useEffect re-executed
  • When dependency, there are a number of variables, a change, it will re-execute the entire useEffect

One problem analysis:

import React, { useEffect, useRef } from "react";
import "./styles.css";

const Profile = () => {
  const [user, setUser] = React.useState({ name: "Alex", weight: 40 });

  React.useEffect(() => {
      console.log("You need to do exercise!");
  }, [user]);

  const gainWeight = () => {
    const newWeight = Math.random() >= 0.5 ? user.weight : user.weight + 1;
    setUser(user 用法=> ({ ...user, weight: newWeight }));
  };

  return (
    <>
      <p>Current weight: {user.weight}</p>
      <button onClick={gainWeight}>Eat burger</button>
    </>
  );
};
用法
export default Profile;

Here you can find find, as long as the click of a button, regardless of whether the increase in numbers, the function will be called useEffect, the fundamental reason is *** useEffect which itself is an element to determine whether the same *** === through, but in the javascrfipt :

[] === [] // false
{} === {} // false

So if it is a reference type, regardless of where a value is changed, the method will be referenced within the useEffect .

Second problem analysis:

import React, { useEffect, useState } from "react";
import "./styles.css";

const Profile = () => {
  const [count, setCount] = useState(0);
  const [simulate, setSimulate] = useState([]);

  useEffect(() => {
    console.log("Number is added!");
  }, [count, simulate]);

  const addList = () => {
    setSimulate(sim => [...sim, Math.random().toFixed(2)]);
  };

  const addNum = () => {
    setCount(Math.random() > 0.5 ? count + 1 : count);
  };

  return (
    <>
      <p>Current weight: {count}</p>
      <button onClick={addList}>增加列表</button>
      <button onClick={addNum}>数字 + 1</button>
    </>
  );
};

export default Profile;

When simulate changes, does call log print, but we might want to print only in the case of increasing the number of (of course this can only count as the dependency), but in some scenarios, and simulate count is coupled, no way to separate. Discussed herein is the use of such a coupling case scenario. Therefore, in order to solve this problem, often you need to know the value of the count when the status update before, but obviously we can not get through the value before the hook function in useEffect.

2. Solution

For a problem: Change the dependencies

For example: Here we only want to monitor changes in weight, and dependencies can be changed user.weight

import React, { useEffect, useRef } from "react";
import "./styles.css";

const Profile = () => {
  const [user, setUser] = React.useState({ name: "Alex", weight: 40 });
  const prevUser = usePrevious(user);

  React.useEffect(() => {
     console.log("You need to do exercise!");
  }, [user.weight]);

  const gainWeight = () => {
    const newWeight = Math.random() >= 0.5 ? user.weight : user.weight + 1;
    setUser(user => ({ ...user, weight: newWeight }));
  };

  return (
    <>
      <p>Current weight: {user.weight}</p>
      <button onClick={gainWeight}>Eat burger</button>
      <Test />
    </>
  );
};

export default Profile;

** For questions I and II: ** state before the acquisition, and then compare after updating

So the question is, how to obtain the state after the previous functional component, with reference to the various articles conclusion, using useRef function, which itself is a value assigned to the data stored by the internal closure, the memory can be a given value

A usePrevious example

import React, { useEffect, useRef } from "react";
import Test from "./Test";
import "./styles.css";

const Profile = () => {
  const [user, setUser] = React.useState({ name: "Alex", weight: 40 });
  const prevUser = usePrevious(user);

  React.useEffect(() => {
    prevUser &&
      user.weight > prevUser.weight &&
      console.log("You need to do exercise!");
  }, [user]);

  const gainWeight = () => {
    const newWeight = Math.random() >= 0.5 ? user.weight : user.weight + 1;
    setUser(user => ({ ...user, weight: newWeight }));
  };

  return (
    <>
      <p>Current weight: {user.weight}</p>
      <button onClick={gainWeight}>Eat burger</button>
      <Test />
    </>
  );
};

export default Profile;

function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}
3. Reference article

Hook to useRef Introduction : This article explains the usage of useRef good and createRef and useRef of!

Published 73 original articles · won praise 6 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_24724109/article/details/104053721