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

React中useState/State页面刷新后无法保留数据求助

问题:页面刷新后React状态丢失,显示空数组

通过npm run dev启动项目时,console.log(filter)能显示数据,但页面一刷新,所有数据就消失,显示空数组[]。

函数组件代码

import "react-table-filter/lib/styles.css";

const TableFilter = dynamic(() => import('react-table-filter'), {
    ssr: false
});

function EventLog({ fullRecords }) {

 const [filter, filterData] = useState(fullRecords);
    console.log(filter);

    const elementsHtml = filter.map((item, index) => {
        return (
            <tr key={"row_" + index}>
                <td className="cell">{datetimestring(item.datetime)}</td>
                <td className="cell">{item.level}</td>
                <td className="cell">{item.code}</td>
                <td className="cell">{item.message}</td>
            </tr>
        );
    });
    const filterUpdateHandler = (newRecords, filtersObject) => {
        filterData(newRecords)
    }
    return (
          <table>
                <thead>
                    <TableFilter rows={filter} onFilterUpdate={filterUpdateHandler}>
                        <th key="date">Date</th>
                        <th key="level" filterkey="level" className="cell">Level</th>
                        <th key="code">Code</th>
                        <th key="message">Message</th>
                    </TableFilter>
                </thead>
                <tbody>
                    {elementsHtml}
                </tbody>
            </table>
     )
}

类组件代码

import React, { Component } from 'react';
import dynamic from 'next/dynamic'

import "react-table-filter/lib/styles.css";

const TableFilter = dynamic(() => import('react-table-filter'), {
    ssr: false
})

function datetimestring(datetime) {
    const ts = new Date(datetime * 1000);
    return ts.toUTCString();
}

class EventLogTableFilter extends Component {

    constructor(props) {
        super(props)

        this.state = {
            records: this.props.records
        }
        console.log(this.props.records)
        this.filterUpdateHandler = this.filterUpdateHandler.bind(this);
    }
    filterUpdateHandler(newData, filtersObject) {
        this.setState({
            records: newData
        });
    }
    render() {
        const record = this.state.records;
        const elementsHtml = record.map((item, index) => {
            return (
                <tr key={"row_" + index}>
                    <td className="cell">{datetimestring(item.datetime)}</td>
                    <td className="cell">{item.level}</td>
                    <td className="cell">{item.code}</td>
                    <td className="cell">{item.message}</td>
                </tr>
            );
        });
        return (
            <table>
                <thead>
                    <TableFilter rows={this.state.records} onFilterUpdate={this.filterUpdateHandler}>
                        <th key="date">Date</th>
                        <th key="level" filterkey="level" className="cell">Level</th>
                        <th key="code">Code</th>
                        <th key="message">Message</th>
                    </TableFilter>
                </thead>
                <tbody>
                    {elementsHtml}
                </tbody>
            </table>
        )
    }
}

解决方案

核心原因

React的useState和类组件的state都是内存中的临时状态,页面刷新时整个应用会重新初始化,内存里的状态会被清空,回到初始值。如果刷新后父组件传递的fullRecords/records是空的,状态自然就变成空数组。

具体解决方法

1. 确保父组件刷新后能传递有效初始数据

如果fullRecords是从API获取的,在Next.js中要确保页面刷新时能重新拿到数据:

  • 用getServerSideProps:每次请求页面时都从服务端获取最新数据,适合实时性要求高的场景。
  • 用getStaticProps:预渲染页面时获取数据,适合静态数据场景,需要配合revalidate做增量更新。

这样刷新页面时,父组件能拿到有效数据并传递给子组件,状态初始化就不会是空数组。

2. 持久化筛选状态到本地存储

如果需要保留用户的筛选结果(刷新后不丢失筛选状态),可以把筛选后的数据存在localStorage或sessionStorage中:

函数组件修改示例:

function EventLog({ fullRecords }) {
  // 初始化时优先读取本地存储的数据,没有则用props传递的初始数据
  const [filter, filterData] = useState(() => {
    const savedFilter = localStorage.getItem('eventLogFilter');
    return savedFilter ? JSON.parse(savedFilter) : fullRecords;
  });

  const filterUpdateHandler = (newRecords) => {
    filterData(newRecords);
    // 把筛选结果存到localStorage
    localStorage.setItem('eventLogFilter', JSON.stringify(newRecords));
  };

  // 空数据时显示加载态,避免报错
  if (!filter?.length) {
    return <div>Loading...</div>;
  }

  // 剩余代码不变...
}

类组件修改示例:

class EventLogTableFilter extends Component {
  constructor(props) {
    super(props);
    const savedFilter = localStorage.getItem('eventLogFilter');
    this.state = {
      records: savedFilter ? JSON.parse(savedFilter) : this.props.records
    };
    this.filterUpdateHandler = this.filterUpdateHandler.bind(this);
  }

  filterUpdateHandler(newData) {
    this.setState({ records: newData });
    localStorage.setItem('eventLogFilter', JSON.stringify(newData));
  }

  render() {
    const { records } = this.state;
    // 空数据时显示加载态
    if (!records?.length) {
      return <div>Loading...</div>;
    }

    // 剩余代码不变...
  }
}

注意:如果数据包含无法JSON序列化的内容(如函数、Symbol),需要先处理这些内容,或者改用其他持久化方案。

3. 处理动态组件的初始化延迟

因为你用了dynamic导入react-table-filter且设置了ssr: false,客户端挂载时组件可能有初始化延迟。可以给表格加个加载状态,避免空数组渲染导致的报错或空白。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:54:28