skip to Main Content

I am working on a React coding challenge (problem link) and the solution is here.

In the problem, the custom hook returns true for the first render, otherwise returns false.

import { useRef } from "react";

export function useIsFirstRender(): boolean {
  const isFirstRender = useRef(true);

  if (isFirstRender.current) {
    isFirstRender.current = false;
    return true;
  }

  return false;
}

In the codes above, I don’t get the way to declare this function. What exactly useIsFirstRender(): boolean {} means?

And since isFirstRender.current is defined as true in the function, It sounds like it will return true at any renders.

Do I misunderstand the usage of useRef? Thank you!

2

Answers


  1. the : boolean is the return type, the data type of the value that this function returns. This is TypeScript syntax and is not part of JavaScript itself.

    As for useRef(true), the true is the initial value. useRef allows you to use persistent values between renders. So your if-statement should work and be true on the first time useIsFirstRender() is called and be false every time after that.

    Login or Signup to reply.
  2. I don’t get the way to declare this function. What exactly useIsFirstRender(): boolean {} means?

    That’s TypeScript code, not JavaScript code. The : boolean part means it returns a boolean value.

    And since isFirstRender.current is defined as true in the function, It sounds like it will return true at any renders.

    isFirstRender.current isn’t always true. useRef gives you a mutable ref object, and it always gives you the same mutable ref object on every call (for that useRef in that hook/component). (The ref object is stored in the instance information of the component this hook is being called by.) In the first call, it initializes the ref object’s current property with the value you provide to useRef, but it only does that during the first call, not subsequent calls. If you can change the current value (as you see that code does), that change endures from call to call. That’s one of the points of refs: They let you store instance-specific, durable information connected to the lifecycle of the element the function component (or the hooks it calls) are managing.

    Here’s an example with some logging that may help clarify it (using just JavaScript, not TypeScript):

    const { useState, useRef } = React;
    
    function useIsFirstRender(): boolean {
        console.log(`useIsFirstRender called`);
        const isFirstRender = useRef(true);
        console.log(`isFirstRender.current = ${isFirstRender.current}`);
    
        if (isFirstRender.current) {
            console.log(`First render; setting isFirstRender.current to false`);
            isFirstRender.current = false;
            return true;
        }
    
        console.log(`Not first render`);
        return false;
    }
    const Example = () => {
        console.log(`Example called`);
        const isFirst = useIsFirstRender();
        const [counter, setCounter] = useState(0);
    
        return (
            <div>
                <div>isFirst: {isFirst}</div>
                <div>
                    Counter: {counter}{" "}
                    <input type="button" value="+" onClick={() => setCounter((c) => c + 1)} />
                </div>
            </div>
        );
    };
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(<Example />);
    <div id="root"></div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

    Notice how the isFirstRender.current value is only true the first time useIsFirstRender is called for the mounted element, not for subsequent calls.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search