Redux Integration - Part 2
This section takes a deeper look at integrating ag-Grid with a Redux store by implementing a feature rich File Browser that uses Tree Data.
Following on from Redux Integration Part 1 we will implement a Redux File Browser to demonstrate how the feature rich ag-Grid can be combined with a Redux store to achieve elegant and powerful grid implementations.
Creating our Redux File Store
Like in Part 1, our Redux File Store is created using the createStore
factory method from the redux
module, and just a single reducer is required:
Our file browser will allow users to create, move and delete files and folders. The logic for handling these
operations is defined in the fileReducer
shown below:
Rather than create action objects directly we shall use the following Action Creators as shown below:
Adding the Provider Component
Now that we have created our Redux store we need to make it available to our React FileBrowser
component. This is achieved through the Provider
component from the react-redux project.
In the entry point of our application we wrap the FileBrowser
component in the Provider
component
as shown below:
The Provider
accepts the store as property and makes it available via props to all child components.
Binding React and Redux
In order for our File Browser to be updated when the store changes we need to bind it.
This is achieved via the connect
function provided by the react-redux project.
In the code above we pass two functions to connect
to map the required state (mapStateToProps) and
actions (mapDispatchToProps). When binding our actions we are using the bindActionCreators
utility
which wraps our action creators into a dispatch
call.
Now that our stateless FileBrowser
component is connected to our Redux store, whenever the file
state in the store changes, our component will re-render with the latest file state available in
this.props.files
.
Adding the Data Table
Now that the Redux store is now connected to our stateless React component, all that remains is to implement the view, which just consists of the ag-Grid Data Table in our File Browser.
Before discussing the grid features in our file browser, here are all of the grid options we are using:
Tree Data
As the data is implicitly hierarchical, with a parent / child relationship between folders and files, we will use
the grids Tree Data feature by setting treeData={true}
.
The file structure in the file browser is captured in the state as an array of files, where each array entry
contains it's hierarchy in the filePath
attribute.
This is supplied to the grid via the callback: getDataPath={data => data.filePath}
.
For more details see our documentation on Tree Data. The mechanism for connecting Redux to ag-Grid applies equally to when the Tree Data feature is not used.
Row Data Updates
The initial file state along with all subsequent state updates will be provided to the grid component via
rowData={this.props.files}
from our Redux file store.
This means the grid does not change the state of the files internally but instead receives the new state from the Redux store!
Context Menu Actions
As shown above, getContextMenuItems={this.getContextMenuItems}
supplies a function to the grid to
retrieve the context menu items. Here is the implementation:
Notice that we are simply just dispatching actions to the Redux store here. For example,
when the new file menu item is selected: action: () => this.props.actions.newFile(filePath)
.
It is important to note that nothing will happen inside the grid when a menu item is selected until the Redux store triggers a re-render of the grid component with the updated state.
For more details see our documentation on Context Menu.
Row Drag Action
Just like the context menu above, we supply a callback function to handle dragging rows via:
onRowDragEnd={this.onRowDragEnd}
. Here is the implementation:
Once again, dragging rows doesn't directly impact the state of the grid. Instead an action is dispatched to the
Redux store using: this.props.actions.moveFiles(movingFilePath, targetPath)
.
For more details see our documentation on Row Dragging.
Delta Row Updates
One consequence of using Redux is that when part of the state is updated in the store, the entire state is replaced with a new version. Delta Row Updates is designed to work specifically with immutable stores such as Redux to ensure only the rows that have been updated will be re-rendered inside the grid.
The file browser enables this feature using: deltaRowDataMode={true}
, along with a required row id
using: getRowNodeId={data => data.id}
.
This feature can lead to noticeable performance improvements in applications which contain alot of row data. For more details see our documentation on Delta Row Updates.
Custom File Cell Renderer
To make our file browser more realistic we will provide a custom Cell Renderer for our files and folders. This is implemented as a react component as follows:
The Cell Renderer is supplied to the grid through: frameworkComponents={this.frameworkComponents}
.
Where frameworkComponents
is just an object referencing the imported component:
The key "fileCellRenderer" is passed by name to the innerRenderer
used in the Auto Group Column:
For more details see our documentation on Custom Cell Renderer Components.
Demo - Redux File Browser
Now we are ready to enjoy the fruits of our labour! The completed Redux File Browser with source code is shown below. In this example you can:
- Right Click on a folder for options to delete the folder or add a new file.
- Right Click on a file for the option to delete the file.
- Click and Drag on the move icon to move files and folders.
Conclusion
In this section we extended the Redux file store introduced in Part 1, to support the additional functionality required by the File Browser, while still maintaining a nice separation of concerns allowing our view components to remain stateless and focused on presentational detail.
We also explored numerous powerful grid features that support complex grid implementations with the minimal of effort, while proving to be extremely flexible. These features included:
- Tree Data
- Custom Context Menu
- Row Dragging
- Delta Row Updates
- Custom Cell Renderer Components