Can useHistory can be used as a value of useRef?

On a whim…🤔
I wrote down the following code

import React, { useRef } from 'react';
import { useHistory } from 'react-router-dom';

// Parent component
const Example: React.FC = () => {
  // Case A:
  const packHistoryToRef = useRef<ReturnType<typeof useHistory>>(useHistory());

  // Case B:
  const history = useHistory();
  

  console.log(packHistoryToRef);    //  It works!😎
  
  return (
    [1, 2, 3, 4, 5].map(i => (
      // Case A solution
      <Child history={packHistoryToRef} />

      // Case B solution
      <Child history={history} /> 
    ))
  )
}


// Child component
const Child = ({ history }) => {
  // Case A: Is `history` object point to the same memory address?

  // Case B: There’s five printouts here. Does that mean it’s gonna repeat it five times?
  console.log(history, 'history')
}


Is it safe for me to use like this?

Otherwise, I think this is the benefit of doing this is

  1. Save memory
  2. Clear
  3. It is very useful in child components (especially in ListItem)

Answer

Can useHistory can be used as a value of useRef

Yes, you can store any value you like into a React ref.

The reason useRef(useHistory()) works is because it still follows the rules of hooks.

It would be equivalent to:

const history = useHistory();
const packHistoryToRef = useRef(history);

The hooks are called in the same order, unconditionally, each render cycle.

Does it

  1. Save memory

    I suppose it saves a single variable declaration. Not much more.

  2. Clear

    It seems clear enough to me, or anyone else familiar with javascript, React, and React hooks. Though generally it is better to be more explicit with what your code is doing than trying to be “fancy”.

  3. It is very useful in child components (especially in ListItem)

    I wouldn’t say it’s any more useful than just explicitly declaring the history object first.

I would suggest sticking to writing code that is more clearly read, each line with a specific purpose.

const history = useHistory();       // (1) define history
const historyRef = useRef(history); // (2) save ref

Update

// Parent component
const Example: React.FC = () => {
  // Case A:
  const packHistoryToRef = useRef<ReturnType<typeof useHistory>>(useHistory());

  // Case B:
  const history = useHistory();
  

  console.log(packHistoryToRef);    //  It works!😎
  
  return (
    [1, 2, 3, 4, 5].map(i => (
      // Case A solution
      <Child history={packHistoryToRef} />

      // Case B solution
      <Child history={history} /> 
    ))
  )
}

As I pointed out in comments, the history object provided by the useHistory hook is basically already a reference to a singular history instance, so storing it in a React ref of your own doesn’t provide any additional benefit. Just pass down history from useHistory to children components.