use-between icon indicating copy to clipboard operation
use-between copied to clipboard

UseEffect: Failing trying to use another hook

Open melloware opened this issue 3 years ago • 5 comments

Code Sandbox: https://codesandbox.io/s/react-router-forked-mnnxb

In the above sandbox I wanted to use a useEffect hook inside my shared hook. For example I want to write a shared hook that listens for location changes and updated the document title like this from React Router...

import React, { useState, useEffect } from "react";
import { useBetween } from "use-between";
import { useLocation } from "react-router-dom";

const useShared = () => {
  const location = useLocation();
  const [value, setValue] = useState(false);
  useEffect(() => {
    document.title = `Location: ${location}`;
    setValue(true);
  }, [location]); // Only re-run the effect page location changes
  return {
    value,
    setValue
  };
};

export const useSharedHook = () => useBetween(useShared);

Is my use case wrong because I get this error:

TypeError
Invalid attempt to destructure non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.

melloware avatar Dec 05 '21 12:12 melloware

Hi @melloware, great catch!

What to say about the error "Invalid attempt to destructure non-iterable instance." This is because the useShared function returns an object (https://codesandbox.io/s/react-router-forked-mnnxb?file=/components/state.js:400-439)

const useShared = () => {
  ...
  return {
    value,
    setValue
  };
};

And inside About and Home, an attempt to access it as an array: (https://codesandbox.io/s/react-router-forked-mnnxb?file=/components/About.js:93-135)

const About = () => {
  const [value, setValue] = useSharedHook();
  ...

Here's a working way (https://codesandbox.io/s/react-router-forked-cbz4b?file=/components/About.js:99-118)


But there is another problem:

The useLocation hook internally uses the React context. The error looks like this:

Hook "useContext" no possible to using inside useBetween scope.

There is no way to use the React context inside shared states, since they exist outside the React component hierarchy.

We will create a component like this (https://codesandbox.io/s/react-router-forked-cbz4b?file=/components/state.js:517-713):

export const SharedConnector = () => {
  const location = useLocation(); // We can only use inside React component's, as it uses the React context internally.

  const {setLocation} = useSharedHook();
  useEffect(() => {
    setLocation(location.pathname); // Set "location.pathname" to the shared state
  }, [location]);
  return null;
};

Which will forward location.pathname inside our shared state.

And put it inside the Router element to use its context. (https://codesandbox.io/s/react-router-forked-cbz4b?file=/index.js:309-323)

const BasicExample = () => (
  <Router>
    <SharedConnector />
    ...

But to my surprise in the final example there is a bug when updating setValue(true) inside useEffect, the component is not updated the first time. I will see it. (https://codesandbox.io/s/react-router-forked-cbz4b?file=/components/state.js:328-342)

betula avatar Dec 06 '21 12:12 betula

Excellent explanation and example!

melloware avatar Dec 06 '21 12:12 melloware

also for the error "Invalid attempt to destructure non-iterable instance." is there any way to catch that error and give the user a better error message about their invalid use of use-between? Because I was stumped at first on what the error was trying to tell me. :)

melloware avatar Dec 06 '21 12:12 melloware

Hi @melloware,

I spent some time with this issue.

But to my surprise in the final example there is a bug when updating setValue(true) inside useEffect, the component is not updated the first time. I will see it. (https://codesandbox.io/s/react-router-forked-cbz4b?file=/components/state.js:328-342)

And I fixed it in version 1.3.1, you can see the result of the work here.

https://codesandbox.io/s/react-router-forked-forked-gntx4?file=/components/state.js (it's just a fork with an updated version).

Try It Out and Happy Coding)

betula avatar Feb 07 '22 12:02 betula

Nice!!!

melloware avatar Feb 07 '22 12:02 melloware