typescript NextJS中的React自定义本地存储挂钩水合错误

mfuanj7w  于 2022-11-30  发布在  TypeScript
关注(0)|答案(1)|浏览(126)

我尝试在NextJS中实现localstorage挂钩,但收到以下错误:Error: Hydration failed because the initial UI does not match what was rendered on the server.。您知道是什么原因导致的吗?在我看来,useEffect函数似乎没有正确使用。如何强制CSR而不是SSR来避免水合错误?

import { useState, useEffect } from 'react';

function useLocalStorage<T>(key: string, initialValue: T) {
    const [storedValue, setStoredValue] = useState<T>(() => {
        if (typeof window === 'undefined') {
            return initialValue;
        }
        try {
            const item = window.localStorage.getItem(key);
            return item ? JSON.parse(item) : initialValue;
        } catch (error) {
            return initialValue;
        }
    });

    useEffect(() => {
        setStoredValue(storedValue);
    }, [storedValue, setStoredValue]);

    // eslint-disable-next-line no-unused-vars
    const setValue = (value: T | ((val: T) => T)) => {
        try {
            const valueToStore = value instanceof Function ? value(storedValue) : value;
            setStoredValue(valueToStore);

            if (typeof window !== 'undefined') {
                window.localStorage.setItem(key, JSON.stringify(valueToStore));
            }
        } catch (error) {
            console.log(error);
        }
    };

    return [storedValue, setValue] as const;
}

export default useLocalStorage;
c2e8gylq

c2e8gylq1#

我知道有两种方法可以消除水合错误。
第一种方法是使用next/dynamic并动态加载,ssr选项传递为false,如下所示:

import dynamic from 'next/dynamic'

   const DynamicHeader = dynamic(() => import('../components/header'), {
     ssr: false,
   })

但是,由于这是一个自定义挂钩,我们只能动态导入组件,所以在这种情况下,您必须正确使用useEffect!
第二个是使用useEffect钩子。我已经在Js中做了这个,希望这有帮助!

import { useEffect, useState } from "react";

export default function useLocalStorage(key, initialValue) {
const [value, setValue] = useState();

useEffect(() => {
const data = localStorage.getItem(key);
if (data === null) {
  if (typeof initialValue === "function") {
    setValue(initialValue());
  } else {
    setValue(initialValue);
  }
 } else {
  setValue(JSON.parse(data));
 }
 }, []);

 useEffect(() => {
     localStorage.setItem(key, JSON.stringify(value));
 }, [value]);

 return [value, setValue];
 }

相关问题