如何无需刷新页面动态切换AgGrid表格的主题背景色?
解决AgGrid主题切换不实时生效的问题
问题根源
当前MyGridComponent作为类组件,isDarkTheme仅在组件初始化(constructor阶段)从localStorage读取一次。当Navbar切换主题修改localStorage后,组件的状态没有触发更新,导致渲染的className不会变化,只有页面刷新重新初始化组件时才会读取新的主题值。
解决方案
方案一:通过Props传递主题状态(推荐,组件通信更规范)
让Navbar维护主题状态,切换时同步将主题值通过props传递给MyGridComponent:
- 在Navbar组件中,切换select选项时,更新
localStorage同时把主题值传给MyGridComponent - 修改
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
相关产品推荐
相关产品推荐

