useEffect очищает localstorage
Суть: когда я создаю новый todo он записывается в localstorage и после перезагрузки страницы хочу чтобы сохранённые todo отображались но localstorage очищается после перезагрузки страницы.
MainPage.tsx
'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 = () => {
useEffect(() => {
set(JSON.parse(localStorage.getItem('todoArray') || '[]'))
}, [])
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>
<div 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>
)}
</div>
</div>
)
}
export default MainPage
useView.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[]>([])
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
}
}
Ответы (2 шт):
Автор решения: Максим
→ Ссылка
const [todo, setTodo] = React.useState<ITodo[]>([])
useEffect(() => {
localStorage.setItem('todoArray', JSON.stringify(todo))
}, [todo])
как я понимаю ты просто перезаписываешь стор при обновлении страницы todo у тебя пустой соответственно у тебя todoArray: [] добавь проверку по типу
if (localStorage.getItem("todoArray") === null ) {
localStorage.setItem('todoArray', JSON.stringify(todo))
}
Автор решения: Armen
→ Ссылка
Если ты используеш localStorage, то локально в коде хранить 'tasks' не совсем правильно, как один единственный источник правды должен выступать localStorage, канечно могут быть случии когда useEffect и все такое будет уместным но не в данном случее
import { useState } from "react";
export const App = () => {
const { addTasks, tasks } = useTasks()
return <div></div>;
};
const useTasks = () => {
const { forceUpdate } = useForceUpdate()
const tasks = localStorage.getItem("tasks") ?? [];
const addTasks = (tasks) => {
localStorage.setItem("tasks", JSON.stringify(tasks));
forceUpdate();
};
return { addTasks, tasks }
};
const useForceUpdate = () => {
const [_, setNum] = useState(0);
const forceUpdate = () => setNum((prev) => ++prev);
return { forceUpdate }
}