0
import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [minus, setMinus] = useState(3);
  const ref = useRef(null);

  const handleClick = () => {
    setMinus(minus - 1);
  };

  console.log(
    "--> ref and state",
    ref.current?.innerHTML ?? ref.current,
    minus
  );

  // first useEffect
  useEffect(() => {
    console.log(`denp[ref.current] >`, ref.current?.innerHTML ?? ref.current);
  }, [ref.current]);

  // second useEffect
  useEffect(() => {
    console.log(`denp[minus]>`, ref.current?.innerHTML ?? ref.current);
  }, [minus]);

  return (
    <div className="App">
      {(minus >= 0 || minus <= -5) && <h1 ref={ref}>num: {minus}</h1>}
      <button onClick={handleClick}>minus</button>
    </div>
  );
}

export default App;

On the first render: the first useEffect is run and log out: denp[ref.current] > num: 3

I press the button, the state minus is updated to 2, the component is re-rendered

On the second render: the first useEffect is run and log out: denp[ref.current] > num: 2

I press the button, the state minus is updated to 1, the component is re-rendered

On the third render: the first useEffect is not run anymore

Why the first useEffect does not run on the third render?

Live code here: https://codesandbox.io/s/brave-mayer-3f8zsl

Willy
  • 145
  • 3
  • 8
  • ref.current doesn't seems to be a reliable dependency, as React is raising this warning: React Hook useEffect has an unnecessary dependency: 'ref.current'. Either exclude it or remove the dependency array. Mutable values like 'ref.current' aren't valid dependencies because mutating them doesn't re-render the component. (react-hooks/exhaustive-deps) – TheTisiboth Feb 17 '22 at 10:38
  • Yes I read the warnings and the doc but I do not know exactly what happened? Can you explain what each re-render does, please? – Willy Feb 17 '22 at 10:44
  • I sadly does't have the knowledge to explain what is happening here, sorry – TheTisiboth Feb 17 '22 at 10:48

3 Answers3

1

if you really want to use ref as a dependency, so use ref.current.innerHTML instead of ref.current. I teseted It with ref.current.innerHTML and it worked for me hope helping you

Mohammad
  • 36
  • 3
  • Yes it worked, maybe it is related to the ref.current which is a DOM node. The DOM Node is the same but different value in the second and third render – Willy Feb 17 '22 at 11:11
0

I guess you should not rely on the ref as a dependency, since it is not triggering updates, as it is said here.

TheTisiboth
  • 1,431
  • 1
  • 6
  • 13
  • Yes, but I really want to know what exactly happened? I did this but in the third render, I expect the useEffect is called - first render - state: 3 - ref: null - render DOM → update ref = 3 - run useEffect → log ref 3 - second render - state: 2 - ref: 3 - compare old ref (null) vs new ref (3) - render DOM → update ref = 2 - run useEffect → log ref 2 - third render - state - ref 0 - compare old ref (3) vs new ref (0) - render DOM → update ref = null - run useEffect → log ref null – Willy Feb 17 '22 at 10:50
  • Yes, I agree that is is weird – TheTisiboth Feb 17 '22 at 10:51
0

If you are using Next.JS (maybe applies to any SSR), I would suggest also setting the dependency to ref.current?.innerHTML and then it will work.

howard
  • 432
  • 3
  • 9