首页 > 解决方案 > 使用 react redux 恢复 Ag Grid 的列状态

问题描述

我在 react+redux 应用程序中使用 Ag Grid。我需要使网格持久化的列状态。换句话说,每当用户对列进行更改(顺序、排序、隐藏\显示等)时,应用程序必须将列状态保存到 DB。然后当用户再次出现时,必须恢复列状态。我的方法是使用在各种事件回调和redux 操作中将columnApi.getColumnState()状态推送到数据库。我没有错误,但是没有应用状态。这是我的组件示例代码(我正在使用):columnApi.setColumnState()componentDidMountreact-thunk

@(connect(selector, { getColumnStateAction, saveColumnStateAction }) as any)
class MyComponent extends Component<Props, {}> {

  private columnApi:any

  onGridReady(params) {
    const { columnState } = this.props
    params.columnApi.setColumnState(columnState)
    this.columnApi = params.columnApi
  } 

  onColumnChanged() {
    saveColumnStateAction(this.columnApi.getColumnState())
  }

  componentDidMount() {
    getColumnStateAction()
  }

  render() {        
    const { columnDefs } this.props
    const gridOptions = {
      columnDefs,
      onGridReady: this.onGridReady,
      onColumnVisible: this.onColumnChanged,
      onColumnResized: this.onColumnChanged,
      onColumnMoved: this.onColumnChanged,
      onColumnPinned: this.onColumnChanged
    }

    <AgGridReact { ...gridOptions } />
  }
}

这是我的行动:

const getColumnStateAction = () => async(dispatch:Dispatch) => {
   const columnState = await fetchFromDb();
   dispatch({ type:'GET_COLUMN_STATE', payload:columnState })
}

const saveColumnStateAction = (columnState:any) => async(dispatch:Dispatch) => {
   await saveToDb(columnState);
   dispatch({ type:'SAVE_COLUMN_STATE' })
}

我的问题是:我应该在何时何地恢复 columnState 以便将其应用于我的网格。关键是我在使用 redux 之前有工作代码。下面的代码有效并且正确应用了状态:

@(connect(selector, { getColumnStateAction, saveColumnStateAction }) as any)
class MyComponent extends Component<Props, {}> {

  private columnApi:any

  onGridReady(params) {
    this.columnApi = params.columnApi
  } 

  async onColumnChanged() {
    await saveToDb(this.columnApi.getColumnState());
  }

  async componentDidMount() {    
    const columnState = await fetchFromDb();
    this.columnApi.setColumnState(columnState)
  }

  render() {
    const { columnDefs } this.props
    const gridOptions = {
      columnDefs,
      onGridReady: this.onGridReady,
      onColumnVisible: this.onColumnChanged,
      onColumnResized: this.onColumnChanged,
      onColumnMoved: this.onColumnChanged,
      onColumnPinned: this.onColumnChanged
    }

    <AgGridReact { ...gridOptions } />
  }
}

所以我怀疑我在 redux 上做错了什么。请帮忙。

标签: reduxag-gridag-grid-reactreact-thunk

解决方案


我想,我已经找到了解决办法。它可能不是最优雅的,但它确实有效。关键是我必须columnApi.setColumnState()在特定时间只调用一次 - after componentDidMountonGridReady并且当列已经出现在网格中时。所以这是我的工作示例:

@(connect(selector, { getColumnStateAction, saveColumnStateAction }) as any)
  class MyComponent extends Component<Props, {}> {

  public state:any = { columnStateSet: false }

  private columnApi:any

  onGridReady(params) {
    const { columnState } = this.props
    this.columnApi = params.columnApi
  } 

  onColumnChanged() {
    saveColumnStateAction(this.columnApi.getColumnState())
  }

  /**
  * Catches a moment for applying persisted column state
  * The point is that previous columnState, that we get from DB, must be applied in specific moment.
  * It must be applied once per loading component after all columns are already set and columnApi becomes available.
  * Otherwise column state will not be applied correctly.
  */
  private onGridColumnsChanged = () => {
    const { columnStateSet } = this.state
    const { columnState } = this.props

    if(this.columnApi && columnState && !columnStateSet) {
      this.columnApi.setColumnState(columnState)
      this.setState({ columnStateSet: true})
    }
  }

  componentDidMount() {
    getColumnStateAction()
    this.setState({ columnStateSet: false })
  }

  render() {
    const { columnDefs } this.props
    const gridOptions = {
      columnDefs,
      onGridReady: this.onGridReady,
      onColumnVisible: this.onColumnChanged,
      onColumnResized: this.onColumnChanged,
      onColumnMoved: this.onColumnChanged,
      onColumnPinned: this.onColumnChanged,
      onGridColumnsChanged: this.onGridColumnsChanged
    }

    <AgGridReact { ...gridOptions } />
  }
}

希望它可以帮助某人。


推荐阅读