You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-grid-layout的onLayoutChange刷新时重置localStorage布局数据如何解决

问题根因
  1. 仅存储了布局配置layouts到localStorage,未存储动态添加的items、charts列表以及计数器newCounter、chartCounter的值,页面刷新后动态添加的元素全部丢失,原有布局和当前元素无法匹配,react-grid-layout会自动生成默认布局覆盖原有存储值。
  2. 组件挂载阶段就会触发onLayoutChange回调,此时直接执行存储逻辑会把初始默认布局覆盖localStorage中存储的自定义布局。
  3. localStorage读写本身是同步API,不存在异步读取未完成的问题,所有异常都来自状态匹配错误和初始化触发的误写入。
修复方案
  • 第一步:抽离统一的全状态保存方法,将布局相关的所有动态状态都存入localStorage
saveAllToLS() {
  if (global.localStorage) {
    global.localStorage.setItem(
      "rgl-8",
      JSON.stringify({
        layouts: this.state.layouts,
        items: this.state.items,
        charts: this.state.charts,
        newCounter: this.state.newCounter,
        chartCounter: this.state.chartCounter
      })
    );
  }
}
  • 第二步:修改初始化逻辑,读取localStorage时恢复所有状态,没有存储值时才用默认值,同时新增挂载标记避免初始化误写入
constructor(props) {
  super(props);
  // 读取存储的全量状态
  const savedState = getFromLS() || {};
  this.state = {
    layouts: savedState.layouts || {},
    inputWidthVal: "",
    inputHeightVal:"",
    // 优先读取存储的元素列表,没有才用默认值
    items: savedState.items || [0, 1, 2, 3, 4].map(function (i) {
      return {
        id: uuidV4(),
        i: i.toString(),
        x: i * 2,
        y: 0,
        w: 1,
        h: 1
      };
    }),
    charts: savedState.charts || [0].map(function (i) {
      return {
        id: uuidV4(),
        i: i.toString(),
        x: i,
        y: 0,
        w: 4,
        h: 3
      };
    }),
    // 优先读取存储的计数器,避免新增元素的i属性重复
    newCounter: savedState.newCounter || 0,
    chartCounter: savedState.chartCounter || 0,
    // 挂载标记,初始化阶段不触发存储逻辑
    isMounted: false
  };

  this.onAddItem = this.onAddItem.bind(this);
  this.onChartItem = this.onChartItem.bind(this);
  this.onBreakpointChange = this.onBreakpointChange.bind(this);
}
  • 第三步:修改getFromLS方法,直接返回全量存储对象
export function getFromLS() {
  if (global.localStorage) {
    try {
      return JSON.parse(global.localStorage.getItem("rgl-8")) || {};
    } catch (e) {
      return {};
    }
  }
  return {};
}
  • 第四步:修改布局变更回调,仅在组件挂载完成后才执行状态更新和存储
componentDidMount() {
  this.setState({ isMounted: true });
}

onLayoutChange(layout, layouts) {
  if (this.state.isMounted) {
    this.setState({ layouts }, () => {
      this.saveAllToLS();
    });
  }
}
  • 第五步:所有元素修改操作(添加/删除元素、清空元素、拖拽新增元素)完成后,都在setState的回调中调用saveAllToLS同步存储,示例如下:
onAddItem() {
  this.setState({
    items: this.state.items.concat({
      id: uuidV4(),
      i: "n" + this.state.newCounter,
      x: (this.state.items.length * 2) % (this.state.cols || 12),
      y: Infinity,
      w: 1,
      h: 1
    }),
    newCounter: this.state.newCounter + 1
  }, () => {
    this.saveAllToLS();
  });
}
// onRemoveItem、onChartItem、clearAllItem、onRemoveChartItem、onDrop方法都按上述逻辑修改即可
  • 额外优化:移除重复的cols配置,static defaultProps里已经定义了cols参数,render中不需要重复传入,避免配置不一致的问题。

内容的提问来源于stack exchange,提问作者yongchang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 11:15:02