React useMemo

useMemo hook helps you to cache variables between re-renders.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { useEffect, useState, useMemo } from "react";
 
 
 
function UserPage() {
 
  const [firstName, setFirstName] = useState("");
 
  const [lastName, setLastName] = useState("");
 
  const [isActive, setIsActive] = useState(false);
 
 
 
  const person = useMemo(() => {
 
    return { firstName, lastName };
 
  }, [firstName, lastName]);
 
 
 
  useEffect(() => {
 
    console.log("person:", person);
 
  }, [person]);
 
 
 
  const handleFirstNameChange = (e) => {
 
    setFirstName(e.target.value);
 
  };
 
 
 
  const handleLastNameChange = (e) => {
 
    setLastName(e.target.value);
 
  };
 
 
 
  const handleActiveChange = (e) => {
 
    setIsActive(e.target.checked);
 
  };
 
 
 
  return (
 
    <form>
 
      <input
 
        type="text"
 
        value={firstName}
 
        onChange={handleFirstNameChange}
 
      />
 
      <input
 
        type="text"
 
        value={lastName}
 
        onChange={handleLastNameChange}
 
      />
 
      <label>
 
        <input
 
          type="checkbox"
 
          checked={isActive}
 
          onChange={handleActiveChange}
 
        />
 
        Active
 
      </label>
 
 
 
      <p>Person: {JSON.stringify(person)}</p>
 
    </form>
 
  );
 
}
 
 
 
export default UserPage;

The 'person' object makes the dependencies of useEffect Hook change on every render. So console.log will run on every checkbox click. To fix this, wrap the initialization of 'person' in its own useMemo() Hook.

The reason of it is because of referential equality and redefining new person object after every re-render.

Also check eslintreact-hooks/exhaustive-deps.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { useEffect, useState } from "react";
 
 
 
function UserPage() {
 
  const [firstName, setFirstName] = useState("");
 
  const [lastName, setLastName] = useState("");
 
  const [isActive, setIsActive] = useState(false);
 
 
 
  const person = { firstName, lastName };
 
 
 
  useEffect(() => {
 
    console.log("person:", person);
 
  }, [person]);
 
 
 
  const handleFirstNameChange = (e) => {
 
    setFirstName(e.target.value);
 
  };
 
 
 
  const handleLastNameChange = (e) => {
 
    setLastName(e.target.value);
 
  };
 
 
 
  const handleActiveChange = (e) => {
 
    setIsActive(e.target.checked);
 
  };
 
 
 
  return (
 
    <form>
 
      <input
 
        type="text"
 
        value={firstName}
 
        onChange={handleFirstNameChange}
 
      />
 
      <input
 
        type="text"
 
        value={lastName}
 
        onChange={handleLastNameChange}
 
      />
 
      <label>
 
        <input
 
          type="checkbox"
 
          checked={isActive}
 
          onChange={handleActiveChange}
 
        />
 
        Active
 
      </label>
 
 
 
      <p>Person: {JSON.stringify(person)}</p>
 
    </form>
 
  );
 
}
 
export default UserPage;

Leave a Comment