当前位置: 首页 > article >正文

react18中如何实现同步的setState来实现所见即所得的效果

在react项目中,实现添加列表项,最后一项自动显示在可视区域范围!!

实现效果请添加图片描述

代码实现

import { useState, useRef } from "react";
import { flushSync } from "react-dom";
function FlushSyncRef() {
  const [msgLists, setMsgList] = useState([]);
  const [msg, setMsg] = useState("");
  const ulRef = useRef(null);
  const handleAdd = (e) => {
    e.preventDefault();
    setMsg("");
    setMsgList((prev) => {
      console.log(prev);
      return [...prev, msg];
    });
    ulRef.current.lastChild.scrollIntoView({
      behavior: "smooth",
      block: "end",
    });
    console.log("🚀 ~ handleAdd ~ ulRef.current:", ulRef.current.lastChild);
  };
  function handleChangeText(e) {
    setMsg(e.target.value);
  }
  return (
    <div>
      <input
        type="text"
        placeholder="Enter your msg"
        value={msg}
        onChange={handleChangeText}
      />
      <button onClick={handleAdd}>添加</button>
      <hr />
      <ul
        style={{ height: "90px", border: "1px solid red", overflow: "auto" }}
        ref={ulRef}
      >
        {msgLists.map((item, index) => {
          return (
            <li key={index}>
              这是第{index}
              {item}
            </li>
          );
        })}
      </ul>
    </div>
  );
}

export default FlushSyncRef;

测试发现,组件崩溃了!!!!!

在这里插入图片描述
意思就是没有找到要滚动的元素,元素为null,上面不存在这个scroll方法。
在默认数据改造下
请添加图片描述
可以发现,最后一项始终慢了一步,不能同步的显示到可视区域。
为啥为这样呢?

在 React 中,state 更新是排队进行的。通常,这就是你想要的。但是,在这个示例中会导致问题,因为 setTodos 不会立即更新 DOM。因此,当你将列表滚动到最后一个元素时,尚未添加待办事项。这就是为什么滚动总是“落后”一项的原因。

要解决此问题,你可以强制 React 同步更新(“刷新”)DOM。 为此,从 react-dom 导入 flushSync 并将 state 更新包裹 到flushSync

  • 修复后的代码
const [msgLists, setMsgList] = useState(["test0000"]);
// ....
const handleAdd = (e) => {
    e.preventDefault();
    flushSync(() => {
      setMsg("");
      setMsgList((prev) => {
        console.log(prev);
        return [...prev, msg];
      });
    });
    ulRef.current?.lastChild?.scrollIntoView({
      behavior: "smooth",
      block: "end",
    });
    console.log("🚀 ~ handleAdd ~ ulRef.current:", ulRef.current.lastChild);
  };
  // ....

这样,再测试就实现了我们的需求了。


http://www.kler.cn/news/359521.html

相关文章:

  • 【C语言】文件操作(2)(文件缓冲区和随机读取函数)
  • 当物理学奖遇上机器学习:创新融合的里程碑
  • Unity修改鼠标指针大小
  • nginx中的HTTP 负载均衡
  • 【python+Redis】hash修改
  • 真空探针台选型需知
  • Spring Boot:如何实现JAR包的直接运行
  • 首个统一生成和判别任务的条件生成模型框架BiGR:专注于增强生成和表示能力,可执行视觉生成、辨别、编辑等任务
  • Android Studio Ladybug指定ndk版本
  • python excel如何转成json,并且如何解决excel转成json时中文汉字乱码的问题
  • Mac 安装 Telnet 工具
  • Maven - Assembly实战
  • ubuntu 虚拟机将linux文件夹映射为windows网络位置
  • Openlayers高级交互(2/20):清除所有图层的有效方法
  • 01 springboot-整合日志(logback-config.xml)
  • 【H2O2|全栈】JS入门知识(五)
  • 前端报错:‘vue-cli-service‘ 不是内部或外部命令,也不是可运行的程序(node_modules下载不下来)
  • 中小型医院网站开发:Spring Boot入门
  • Mac 查看编译器默认使用C++标准
  • C语言【调试】(个人笔记版)