我正在尝试将值保存在本地存储中。当我单击“设置项目”时,它第一次在本地存储上保存一个空数组。之后这段代码就可以正常工作了。我是反应和TS的初学者。这是下面的代码。
hooks/useLocalStorage.ts
function useLocalStorage(key: string) {
/* Set Item to Localstorage */
const set = (value: unknown) => {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.log((error as Error)?.message);
}
};
/* Get Item from Localstorage */
const get = () => {
try {
return localStorage.getItem(key);
} catch (error) {
console.log(error);
}
};
/* Remove Item */
const clean = () => {
try {
localStorage.removeItem(key);
} catch (error) {
console.log((error as Error)?.message);
}
};
return { set, get, clean };
}
export { useLocalStorage };
App.tsx
import { Button, ButtonGroup, TextField } from "@mui/material";
import { useState } from "react";
import { useLocalStorage } from "./hooks/useLocalStorage";
function App() {
type TProp = {
title: string;
};
const [value, setValue] = useState("");
const { set, get, clean } = useLocalStorage("todos");
const [todos, setTodos] = useState<TProp[]>([]);
/* Set Item */
const setItem = () => {
setTodos([...todos, { title: value }]);
set(todos);
};
return (
<>
<TextField
label="Enter Text"
variant="outlined"
fullWidth
margin="normal"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<ButtonGroup variant="contained" fullWidth>
<Button onClick={setItem}>Set Item</Button>
<Button color="success" onClick={() => console.log(get())}>
Get Item
</Button>
</ButtonGroup>
<Button
variant="contained"
color="error"
fullWidth
sx={{ mt: 2 }}
onClick={clean}
>
Remove Item
</Button>
</>
);
}
export default App;
main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
我尝试记录来自 useLocalStorage 和 App.tsx 的值。
使用 useEffect 钩子创建一个具有相同名称的空数组,但未进行 wprked。
App.tsx
/** ... **/
useEffect(() => {
if(get()?.length === 0) {
/* todos is empty at this moment */
set(todos)
}
},[])
/** ... **/
上面的代码工作完美,正如预期的那样,它在本地存储中创建了一个名为 todos 的空数组,但如果我在输入上添加一些值并第一次单击 Set ,它仍然不起作用。
由于 react
setState
是异步的,[github] 你不会在 todos
之后立即获得更新的 setTodos([...todos, { title: value }])
,所以不要依赖 todos
在 set(todos)
触发时保持最新状态.
我建议创建一个临时的事实来源,
setTodos
和set
都可以从中获得他们的论点。
因此:
const setItem = () => {
let __temp = [...todos, { title: value }];
setTodos(__temp);
set(__temp); /* <—- I no longer depend on setTodos updating todos because I now have my own source of truth. */
};