1

I have this situation and I don't know why is happening..

I have a custom hook that holds a variable that I can't initialize until another function is executed.

I think it's not about a sync situation because the console.log( '..', name ) is showing the value of the variable before the execution of the useEffect(), also I put a button to manually trigger the useEffect hook (using another state variable and changing his value in the onClick function) and the value was also undefined.

export const useMagic = () => {
 ...
 let name: string;
 ...

 const initMagic = async () => {
      ...     
      name= 'Copperfield';
      console.log('the value of the variable is:', name);
      ...
 }

 useEffect(()=> {
      const loadRabbit = async () => {
          console.log('The name is', name); //undefined *** HERE IS THE PROBLEM ***
      }

      loadRabbit();
      
}, [someDeps]); // I can't put name inside the dependencies because is used before being assigned. I can't initialize the variable because I need another value to create it. 

}

I solved the situation using useRef on the variable and putting it in the dependency array.

But, why is this happening ? There's something that I don't know about how React manages the values of the variables..

Thanks!

1 Answers1

2

You are declaring a local variable inside the useMagic hook.

This means that each time your hook gets called you're getting a new name variable, which is undefined. Your async initMagic keeps a reference to a particular name thru closures. That's why it prints the right value.

If you want to keep values between re-renders (multiple calls to your component/hook) you need to use useState or useRef.

This is what they actually do behind the scenes: they return the store values between re-renders(calls).

So this would be a fix to your problem:

const [name, setName] = useState();

const initMagic = async () => {
      ...     
      setName('Copperfield');
      console.log('the value of the variable is:', name);
      ...
 }

Now you can use name as a proper dep for any useEffect.

Radu Diță
  • 13,476
  • 2
  • 30
  • 34
  • Thanks! I didn't know that the variable inside the custom hook is created in every render. I can't use state because I need the value after initMagic() but before the next render. – Mauricio Etchevest Feb 15 '22 at 14:48
  • Why do you need it before the next render? They way you should think about this is that you don't care about next renders. Everytime something changes, a state, anyone interested in that will re-render. You shouldn't have logic regarding when a re-render is done. – Radu Diță Feb 16 '22 at 09:25
  • I'm working with two custom hooks and a duckdb (a database in the front) which have async methods, the piece of data that I was missing is the connection to that db, so I set up the database then load data, and then render. The problem was to access the connection between the method where I set up the database and where I load the data, and also, keep a reference to that connection without changing it or generating again. – Mauricio Etchevest Feb 16 '22 at 18:17