Matster2
Matster2

Reputation: 147

Values Not Interested In From Hook Causes Re-Render

Lets say I create a custom hook which will return some state and a function so modify that state.

I use this hook with a component and only care about the function it returns and not the state. So I deconstruct the function from the hook.

When i call this function, because I am using the hook (regardless of if I care or get the state of it) it appears to cause a re-render on the component, because the hook is going to update.

I have created an example of this here

Below is a copy of the code:

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

import "./styles.css";

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

  const changeCount = newCount => {
    setCount(newCount);
  };

  console.log("useCount: " + count);

  return {
    count,
    changeCount
  };
};

const App = () => {
  const { changeCount } = useCount();

  const handleOnClick = () => {
    const newCount = Math.floor(Math.random() * 10 + 1);
    console.log("new count: " + newCount);
    changeCount(newCount);
  };

  console.log("app render");

  return (
    <div>
      <button type="button" onClick={handleOnClick}>
        Click Me Boi!
      </button>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

When you click the button, it causes a re-render of the App component, which is, i assume because the hook's state is going to update, and even though you aren't retrieving that state from the hook as such, you are still dependent on the hook.

so my question is is that correct? and if so, is there a way to stop my app component re-rendering if it hasn't/doesn't care about the state, and only cares about the function?

Is the render unavoidable because event if I did call the function, it would still need to update because the function has actually changed because it itself relies on the setCount which will get updated?

Any help would be much appreciated :)

Upvotes: 0

Views: 26

Answers (1)

Ori Drori
Ori Drori

Reputation: 192527

Setting the state via the useState() updater causes the rerender. If you want to cache the current value, but you don't want to cause a rerender, assign the value to a ref:

const { useRef } = React;

const useCount = () => {
  const count = useRef(0);

  const changeCount = newCount => {
    count.current = newCount;
    console.log("useCount: " + count.current);
  };

  return [
    changeCount
  ];
};

const App = () => {
  const [changeCount] = useCount();

  const handleOnClick = () => {
    const newCount = Math.floor(Math.random() * 10 + 1);
    console.log("new count: " + newCount);
    changeCount(newCount);
  };

  console.log("app render");

  return (
    <div>
      <button type="button" onClick={handleOnClick}>
        Click Me Boi!
      </button>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

Upvotes: 1

Related Questions