0

I'm been using useContext to get my variables from one page to the other and I implemented localStorage so I refresh the page. However, when I refresh my portals page I'm getting this error: JSON Parse error: Unexpected identifier "undefined"

The weird part is that, if I refresh it's child page editPortal, I get no error!

Can someone help me please?

_app.tsx :

import { PortalContext } from '../context/PortalContext';

function MyApp({ Component, pageProps }) {
  const [portal, setPortal] = useState<Portal>();
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const portal = localStorage.getItem('portal');

    if (portal) {
      setPortal(JSON.parse(portal));
    }

    setLoading(false);
  }, []);

  function choosePortal(portal: Portal) {
    setPortal(portal);
    if (typeof window !== 'undefined') {
      localStorage.setItem('portal', JSON.stringify(portal));
    }
  }
  return (
    <PortalContext.Provider value={{ portal, escolhePortal, loading }}>
      <main>
        <Header />
        <Component {...pageProps} />
      </main>
    </PortalContext.Provider>
  );
}

portals.tsx

export default function Portals() {
  const router = useRouter();
  const { choosePortal } = useContext(PortalContext);
  const baseName = Array.isArray(router.query.baseName)
    ? router.query.nomeBase[0]
    : router.query.nomeBase;

  const portal: Portal = GetPortals(baseName);
  choosePortal(portal);

  if (portal) {
    return <h1>portal.title</h1>
  }

Thanks a lot!

Rafael
  • 191
  • 1
  • 11
  • 1
    Have you checked what the value of `portal` is before you try to parse it? – Pointy May 27 '21 at 14:14
  • This is probably because your local storage item is holding the value `undefined` which is not valid JSON. Valid JSON starts with `{` and ends with `}`. Every key should be a string, every value should be an array/object/string/integer. – Dimitar May 27 '21 at 14:16
  • @DimitarDev - JSON doesn't have to start with `{` and end with `}`. `[1]` is valid JSON, as are `"1"` (with the actual quotes) and `1`. (The latter two were, years ago, considered JSON "fragments" but that concept died out very early on. And top-level arrays have always been valid.) – T.J. Crowder May 27 '21 at 14:17
  • @DimitarDev however the `JSON.parse()` call is inside a test for truthiness of the value. – Pointy May 27 '21 at 14:17
  • 1
    Well `.setItem()` will convered a "real" `undefined` value to the *string* `"undefined"`, so probably something is goofing up initializing the property at that point. When `.getItem()` is called, it will return that string, and the `if (portal)` test will succeed. – Pointy May 27 '21 at 14:19
  • 1
    Since the only possible values you'll get from `getItem` are `null` and a string, I'm guessing that you've accidentally stored the string `"undefined"` in local storage (probably by storing `undefined` there; it will get automatically converted to string). Since `"undefined"` is truthy, it passes your `if (portal)` test. But it isn't valid JSON, because its string value is just `undefined` which isn't in the JSON vocabulary. Your best bet is probably to chase down where you're storing `undefined`. – T.J. Crowder May 27 '21 at 14:20

1 Answers1

0

Thank you guys for your considerations and questions!

I believe I was storing an undefined portal, which happened before the finished.

I simply added an extra verification && portal before setting the localStorage:

  function choosePortal(portal: Portal) {
    setPortal(portal);
    if (typeof window !== 'undefined' && portal) {
      localStorage.setItem('portal', JSON.stringify(portal));
    }
  }
Rafael
  • 191
  • 1
  • 11