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

如何无需刷新页面动态切换AgGrid表格的主题背景色?

解决AgGrid主题切换不实时生效的问题

问题根源

当前MyGridComponent作为类组件,isDarkTheme仅在组件初始化(constructor阶段)从localStorage读取一次。当Navbar切换主题修改localStorage后,组件的状态没有触发更新,导致渲染的className不会变化,只有页面刷新重新初始化组件时才会读取新的主题值。


解决方案

方案一:通过Props传递主题状态(推荐,组件通信更规范)

让Navbar维护主题状态,切换时同步将主题值通过props传递给MyGridComponent:

  1. 在Navbar组件中,切换select选项时,更新localStorage同时把主题值传给MyGridComponent
  2. 修改MyGridComponent接收props并监听变化:
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
class MyGridComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isDarkTheme: props.theme || localStorage.getItem('themename') || 'light',
      columnDefs: [
        { headerName: 'Make', field: 'make' },
        { headerName: 'Model', field: 'model' },
        { headerName: 'Price', field: 'price' }
      ],
      rowData: [
        { make: 'Toyota', model: 'Celica', price: 35000 },
        { make: 'Ford', model: 'Mondeo', price: 32000 },
        { make: 'Porsche', model: 'Boxster', price: 72000 }
      ]
    };
  }

  // 监听props变化,更新主题状态
  componentDidUpdate(prevProps) {
    if (prevProps.theme !== this.props.theme) {
      this.setState({
        isDarkTheme: this.props.theme
      });
    }
  }

  render() {
    const {isDarkTheme} = this.state;
    return (
      <div
        className={isDarkTheme === 'dark' ? 'ag-theme-alpine-dark' : 'ag-theme-alpine'}
        style={{
          height: '500px',
          width: '600px'
        }}
      >
        <AgGridReact
          columnDefs={this.state.columnDefs}
          rowData={this.state.rowData}
        />
      </div>
    );
  }
}
export default MyGridComponent;

Navbar调用组件时传递主题值:

<MyGridComponent theme={currentTheme} />

方案二:监听localStorage的storage事件

如果不想通过props传递,可以在MyGridComponent中监听storage事件,当themename变化时更新状态:

import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
class MyGridComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isDarkTheme: localStorage.getItem('themename') || 'light',
      columnDefs: [
        { headerName: 'Make', field: 'make' },
        { headerName: 'Model', field: 'model' },
        { headerName: 'Price', field: 'price' }
      ],
      rowData: [
        { make: 'Toyota', model: 'Celica', price: 35000 },
        { make: 'Ford', model: 'Mondeo', price: 32000 },
        { make: 'Porsche', model: 'Boxster', price: 72000 }
      ]
    };
    this.handleStorageChange = this.handleStorageChange.bind(this);
  }

  componentDidMount() {
    window.addEventListener('storage', this.handleStorageChange);
  }

  componentWillUnmount() {
    window.removeEventListener('storage', this.handleStorageChange);
  }

  handleStorageChange(e) {
    if (e.key === 'themename') {
      this.setState({
        isDarkTheme: e.newValue || 'light'
      });
    }
  }

  render() {
    const {isDarkTheme} = this.state;
    return (
      <div
        className={isDarkTheme === 'dark' ? 'ag-theme-alpine-dark' : 'ag-theme-alpine'}
        style={{
          height: '500px',
          width: '600px'
        }}
      >
        <AgGridReact
          columnDefs={this.state.columnDefs}
          rowData={this.state.rowData}
        />
      </div>
    );
  }
}
export default MyGridComponent;

注意:storage事件仅在同源的其他窗口/标签页修改localStorage时触发,同一页面内修改需额外手动触发状态更新。


方案三:改用函数组件+useEffect(结合Context更佳)

如果项目允许,将类组件转为函数组件,通过useEffect监听主题变化,或用React Context全局管理主题:

import { AgGridReact } from 'ag-grid-react';
import { useState, useEffect } from 'react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';

const MyGridComponent = () => {
  const [isDarkTheme, setIsDarkTheme] = useState(localStorage.getItem('themename') || 'light');

  useEffect(() => {
    const handleStorageChange = (e) => {
      if (e.key === 'themename') {
        setIsDarkTheme(e.newValue || 'light');
      }
    };

    // 监听跨窗口storage变化
    window.addEventListener('storage', handleStorageChange);

    // 监听同一页面内的自定义主题变化事件
    const handleThemeChange = (e) => {
      setIsDarkTheme(e.detail.theme);
    };
    window.addEventListener('themeChange', handleThemeChange);

    return () => {
      window.removeEventListener('storage', handleStorageChange);
      window.removeEventListener('themeChange', handleThemeChange);
    };
  }, []);

  const columnDefs = [
    { headerName: 'Make', field: 'make' },
    { headerName: 'Model', field: 'model' },
    { headerName: 'Price', field: 'price' }
  ];

  const rowData = [
    { make: 'Toyota', model: 'Celica', price: 35000 },
    { make: 'Ford', model: 'Mondeo', price: 32000 },
    { make: 'Porsche', model: 'Boxster', price: 72000 }
  ];

  return (
    <div
      className={isDarkTheme === 'dark' ? 'ag-theme-alpine-dark' : 'ag-theme-alpine'}
      style={{ height: '500px', width: '600px' }}
    >
      <AgGridReact columnDefs={columnDefs} rowData={rowData} />
    </div>
  );
};

export default MyGridComponent;

此时Navbar切换主题时,除了更新localStorage,还要触发自定义事件:

// Navbar中切换主题的处理函数
const handleThemeChange = (e) => {
  const theme = e.target.value;
  localStorage.setItem('themename', theme);
  // 触发自定义事件通知组件更新
  window.dispatchEvent(new CustomEvent('themeChange', { detail: { theme } }));
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 02:36:02