我是个新手,我不知道我用useEffect号钩子有什么问题.代码编译成功,似乎一切正常.用户添加的组件显示在浏览器上并添加到localStorage中,但刷新后,仅显示示例组件(框1),用户所做的输入将丢失.你知道问题出在哪里吗?

mport React, { Fragment, useState, useRef, useEffect } from 'react';
import { v4 as uuidv4} from 'uuid';
import { BoxList } from './components/BoxList';
import { SearchBox } from './components/SearchBox';

const KEY = "boxApp.boxes";

export function App() {
  const [boxes, setBoxes] = useState([ {id: 1, title: 'Box 1', content: 'This is just an example of a box, remove it and create yours!' } ])
  
  const boxTitleRef = useRef();
  const boxContentRef = useRef();

  useEffect(() => {
    const storedBoxes = JSON.parse(localStorage.getItem(KEY));
    if (storedBoxes) {
      setBoxes(storedBoxes);
    }
  }, []);

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

  const removeBox = (id) => {
    const remainingBoxes = boxes.filter((box) => box.id !== id);
    setBoxes(remainingBoxes);
  }

  const addNewBox = (evt) => {
    evt.preventDefault();
    const boxTitle = boxTitleRef.current.value;
    const boxContent = boxContentRef.current.value;
    if (boxTitle === '' || boxContent === '') return;
    setBoxes( previousBoxes => {
      return ([...previousBoxes, { id: uuidv4(), title: boxTitle, content: boxContent}])
    });

    boxTitleRef.current.value = null;
    boxContentRef.current.value = null;
  }

  return (
    <Fragment>
      <SearchBox  />
      <div>
        <h2>Add a box</h2>
        <form>
         <input type='text' placeholder='Title' ref={boxTitleRef}></input>
          <input type='text' placeholder='Content' ref={boxContentRef}></input>
          <button type='submit' onClick={addNewBox}>➕</button>
        </form>
      </div>
      <BoxList boxes={boxes} removeBox={removeBox}/>
    </Fragment>
  );
}

export default App;

推荐答案

问题来自以下useEffect个方面:

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

它会在boxes每次更改时更新localStorage,也会在组件第一次安装时更新,此时boxes等于给定给useState的初始状态.您可以删除它,并在添加和删除项目时更新localStorage:

const addNewBox = (evt) => {
  evt.preventDefault();
  const boxTitle = boxTitleRef.current.value;
  const boxContent = boxContentRef.current.value;
  if (boxTitle === "" || boxContent === "") return;
  const newBoxes = [...boxes, { id: uuidv4(), title: boxTitle, content: boxContent }];
  setBoxes(newBoxes);
  localStorage.setItem(KEY, JSON.stringify(newBoxes));
  boxTitleRef.current.value = null;
  boxContentRef.current.value = null;
};
const removeBox = (id) => {
  const remainingBoxes = boxes.filter((box) => box.id !== id);
  localStorage.setItem(KEY, JSON.stringify(remainingBoxes));
  setBoxes(remainingBoxes);
};

您还可以将您的useState呼叫更改为:

const [boxes, setBoxes] = useState(JSON.parse(localStorage.getItem(KEY)) || [ {id: 1, title: 'Box 1', content: 'This is just an example of a box, remove it and create yours!' } ]);

并删除以下useEffect个:

useEffect(() => {
  const storedBoxes = JSON.parse(localStorage.getItem(KEY));
  if (storedBoxes) {
    setBoxes(storedBoxes);
  }
}, []);

Javascript相关问答推荐

Next.js Next/Image图像隐含性有任何类型-如何修复?

将数据从strapi提取到next.js,但响应延迟API URL

有Angular 的material .未应用收件箱中的价值变化

如何分配类型脚本中具有不同/额外参数的函数类型

在JavaScript中声明自定义内置元素不起作用

Angular:动画不启动

简单的PayPal按钮集成导致404错误

在WordPress中使用带有WPCode的Java代码片段时出现意外令牌错误

查询参数未在我的Next.js应用路由接口中定义

使用Nuxt Apollo在Piniastore 中获取产品细节

如何使用TypeScrip设置唯一属性?

Vaadin定制组件-保持对javascrip变量的访问

获取';无法解决导入和导入";slick-carousel/slick/slick-theme.css";';错误

Next.js中的服务器端组件列表筛选

我想使用GAS和HTML将从Electron 表格中获得的信息插入到文本字段的初始值中

在不扭曲纹理的情况下在顶点着色器中旋转UV

如何在AG-Grid文本字段中创建占位符

通过解构/功能组件接收props-prop验证中缺少错误"

更改管线时不渲染组件的react

在不使用AJAX的情况下将JavaScript数组值传递给Laravel控制器?