Hydration failed because the initial UI does not match what was rendered on the server

я впервые использую nextJS (версия 14.2.5) и столкнулся с данной проблемой: введите сюда описание изображения когда localStorage('todoArray') пуст ошибки нету, но когда нет то вылазит подобная ошибка. Как можно +- адекватно это пофиксить?

useTodo.ts

import React, { FormEvent, useEffect } from "react"


export interface ITodo {
    id: number
    title: string
    description: string
}

export interface IUseTodoReturn {
    functions: {
        create: (title: string, description: string) => void
        delete: (id: number) => void
    }
    get: ITodo[]
    set: (array: ITodo[]) => void
}


export const useTodo = (): IUseTodoReturn => {


    const [todo, setTodo] = React.useState<ITodo[]>(typeof window !== 'undefined' ? JSON.parse(localStorage.getItem('todoArray') || '[]') : [])

    useEffect(() => {
        localStorage.setItem('todoArray', JSON.stringify(todo))
    }, [todo])

    const set = (array: ITodo[]) => {
        setTodo(array)
    }

    const createTodo = (title: string, description: string): void => {
        setTodo([...todo, { id: Date.now(), title, description }])
    }


    const deleteTodo = (id: number) => {
        const filteredArray = todo.filter(todo => todo.id !== id)
        setTodo(filteredArray)
    }


    return {
        functions: { create: createTodo, delete: deleteTodo },
        get: todo,
        set
    }
}
'use client'
import React, { FormEvent, forwardRef, useEffect, useRef, useState } from 'react'
import { Box, Button, Stack, TextField, Typography } from '@mui/material'
import styles from './mainPage.module.scss'
import { useTodo } from '../../hooks/useTodo'
import { describe } from 'node:test'

const MainPage = () => {

    const { functions, get, set } = useTodo()
    const titleRef = useRef<HTMLInputElement>()
    const descRef = useRef<HTMLInputElement>()
   

    const sendTodo = (e: FormEvent) => {
        e.preventDefault()
        if (!titleRef.current?.value || !descRef.current?.value) return
        functions.create(titleRef.current.value, descRef.current.value)
        titleRef.current.value = ''
        descRef.current.value = ''
    }

    return (
        <div className={styles.root}>
            <Stack className={styles.form} spacing={1} component='form' onSubmit={(e) => sendTodo(e)}>
                <TextField inputRef={titleRef} sx={{ width: '30%' }} id="outlined-basic" label="Outlined" variant="outlined" />
                <TextField inputRef={descRef} sx={{ width: '30%' }} id="outlined-basic" label="Outlined" variant="outlined" />
                <Button sx={{ width: '30%' }} type='submit' variant='outlined'>Create</Button>
            </Stack>
            <Stack direction='row' gap={1} alignItems='center' justifyContent='center' className={styles.todoView}>
                {get.map((todo, i) =>
                    <Box key={i} className={styles.todoBody}>
                            <Stack gap={1} flexDirection='row' alignItems='center'>
                                <Typography variant='h6'>{i + 1}.</Typography>
                                <Typography variant='h6'>{todo.title}</Typography>
                            </Stack>
                            <Typography sx={{ wordWrap: 'break-word' }}>{todo.description}</Typography>
                            <Button sx={{ mt: 1 }} variant='contained' onClick={() => functions.delete(todo.id)} color='error'>Delete</Button>
                    </Box>
                )}
            </Stack>
        </div>
    )
}

export default MainPage


Ответы (0 шт):