DEV Community

Cover image for Tutorial: Remix - Material DataGrid
Chris Benjamin
Chris Benjamin

Posted on

Tutorial: Remix - Material DataGrid

Summary

This tutorial covers working with Material DataGrid (x-data-grid) in Remix (https://remix.run). It will cover standard DataGrid render, and then also using Remix Loader to render the DataGrid. This tutorial will cover JavaScript.

We will create this DataGrid in this tutorial
Example of finished product DataGrid

I created this tutorial after personally adding DataGrid to a Remix project I'm working on where I'm pulling data from a SqlLite Database using Prisma. I wanted to use DataGrid to display the data in the admin dashboard. From this I created a quick tutorial to hopefully benefit at least one other person with the same goal in the future.

Github Code Links:

Phase One: https://github.com/cbenjamin2009/Remix-DataGrid-Example-Tutorial/tree/phase-one

Finished: https://github.com/cbenjamin2009/Remix-DataGrid-Example-Tutorial

What is DataGrid?

Material UI DataGrid is an extremely powerful table grid layout for data in a React based project. It's very simple to use, comes with a free and paid version, and can be adapted into a Remix project with ease.
See MUI for Further

Getting Started Phase-One

First we will need to setup our Remix project using default basic application and JavaScript type.
npx create-remix@latest

Then we will install Material UI and DataGrid dependencies
npm i @mui/material @mui/x-data-grid @emotion/react @emotion/styled

Let's create a new file under routes called datagrid.jsx

Setup the base file as such:



import { DataGrid } from "@mui/x-data-grid";

export default function Index() {
    let rows = [];
    let columns = [];
 return (
    <div>
        <header>
        <h1>DataGrid Component</h1>
        </header>

        <section id="DataGrid" style={{ height: 350, width: '50%', marginLeft: 'auto', marginRight: 'auto' }}>
            <DataGrid rows={rows} columns={columns} sx={{backgroundColor: "#caffca"}}/>
        </section>

    </div>
  )
}



Enter fullscreen mode Exit fullscreen mode

For DataGrid to work, it requires at least a height in it's parent container, and information for the rows and columns. In this case we are going to set the height of the parent section to 350px and the width to 100%. We are going to pull the rows and columns. Let's add that data now.

Rows are key-value pair objects, meaning you must map the column names to their values. Each row should contain an 'id' reference. We will then use these row names for the columns property.
Update rows as follows:



    let rows = [
        { id: 1, firstName: 'Jamaal', lastName: 'Gorczany',  email: 'jg@example.com' },
        { id: 2, firstName: 'Deon', lastName: 'Jast', email: 'dj@example.com'},
        { id: 3, firstName: 'Francisca', lastName: 'Lowe', email: 'fl@example.com'},
        { id: 4, firstName: 'Christine', lastName: 'Hermiston', email: 'ch@example.com'},
        { id: 5, firstName: 'Gunner', lastName: 'Will', email: 'gw@example.com'},
        { id: 6, firstName: 'Ereyn', lastName: 'David', email: 'ed@example.com'},
        { id: 7, firstName: 'Ambrose', lastName: 'Johnston', email: 'aj@example.com'},
        { id: 8, firstName: 'Telly', lastName: 'Witting', email: 'tw@example.com'},
        { id: 9, firstName: 'John', lastName: 'Gutman', email: 'jg@example.com'},
        { id: 10, firstName: 'Spencer', lastName: 'Kemmer', email: 'sk@example.com'},
        { id: 11, firstName: 'Holly', lastName: 'Parisian', email: 'hp@example.com'},
        { id: 12, firstName: 'Jonas', lastName: 'Ambrose', email: 'ja@example.com'},
        { id: 13, firstName: 'Mark', lastName: 'Smith', email: 'ms@example.com'},
        { id: 14, firstName: 'Carole', lastName: 'Spencer', email: 'cs@example.com'},
        { id: 15, firstName: 'Rebecca', lastName: 'Nelson', email: 'rn@example.com'},
    ];


Enter fullscreen mode Exit fullscreen mode

Now let's update the Columns based on the rows. We know we will need a firstName, lastName, and email field. We will also set flex so the columns can grow if needed



    let columns = [
        {field: 'firstName', headerName: 'First Name', flex: 1},
        {field: 'lastName', headerName: 'Last Name', flex: 1},
        {field: 'email', headerName: 'Last Name', flex: 1},
    ];


Enter fullscreen mode Exit fullscreen mode

Let's have a run to see how our site looks. Open the console and type npm run dev

  • Note at the time of writing there is an issue with Remix github ```

Unexpected Server Error
TypeError: isbot is not a function

If you receive an error about isbot is not a function, do the following. Open the `entry.server.jsx` file and modify the line `const isbot = require("isbot").default;` to `const isbot = require("isbot"); // remove the .default;`

If you followed along with this tutorial, you should receive this result:
![Website with header DataGrid Component and green table in the middle, three columns for First Name, Last Name, and Email. Random sample data is included](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/96077ltzwx9d0oomgj6n.png)

**You have completed Phase-One of the tutorial**. Your code should match the Phase-One branch in the Github repo if you are having any difficulties please compare your code to this repo. 


## Loading data using Remix useLoaderData()
With Remix we have the useLoaderData() function for pulling in data. This could be pulling in data from a database or from an API or from a local file. Regardless of the source, we can use this function to pull in our row data to be mapped to the DataGrid. This tutorial will keep it simple and pull the data from a local file that contains our data. 

Create a new folder called `data` in the `app` folder. 
Create a new file called `data.js` in the `data` folder

![Development IDE window showing folder structure of App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqdykisw6moefjr6kkrm.png)

Inside Data.js update with the same data we used previously as follows:
```javascript


const sampleData = [
    { id: 1, firstName: 'Jamaal', lastName: 'Gorczany',  email: 'jg@example.com' },
    { id: 2, firstName: 'Deon', lastName: 'Jast', email: 'dj@example.com'},
    { id: 3, firstName: 'Francisca', lastName: 'Lowe', email: 'fl@example.com'},
    { id: 4, firstName: 'Christine', lastName: 'Hermiston', email: 'ch@example.com'},
    { id: 5, firstName: 'Gunner', lastName: 'Will', email: 'gw@example.com'},
    { id: 6, firstName: 'Ereyn', lastName: 'David', email: 'ed@example.com'},
    { id: 7, firstName: 'Ambrose', lastName: 'Johnston', email: 'aj@example.com'},
    { id: 8, firstName: 'Telly', lastName: 'Witting', email: 'tw@example.com'},
    { id: 9, firstName: 'John', lastName: 'Gutman', email: 'jg@example.com'},
    { id: 10, firstName: 'Spencer', lastName: 'Kemmer', email: 'sk@example.com'},
    { id: 11, firstName: 'Holly', lastName: 'Parisian', email: 'hp@example.com'},
    { id: 12, firstName: 'Jonas', lastName: 'Ambrose', email: 'ja@example.com'},
    { id: 13, firstName: 'Mark', lastName: 'Smith', email: 'ms@example.com'},
    { id: 14, firstName: 'Carole', lastName: 'Spencer', email: 'cs@example.com'},
    { id: 15, firstName: 'Rebecca', lastName: 'Nelson', email: 'rn@example.com'},
]

export default sampleData;


Enter fullscreen mode Exit fullscreen mode

Let's go back to the datagrid.jsx file and begin to pull the data from this file.

Update the imports



import { DataGrid } from "@mui/x-data-grid";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import sampleData  from "~/data/data"


Enter fullscreen mode Exit fullscreen mode

Now create the loader function to load our sampleData



export async function loader() {
    return json(sampleData);
}


Enter fullscreen mode Exit fullscreen mode

Perfect, now we can pull this loaderData by updating the Index() function as follows



export default function Index() {

    let data = useLoaderData();
    //row data contains a unique ID for each row and sample data with first name, last name, and email address
    // map through our loaded data and return the row fields
    let rows = data.map((user) => {
        return {
            id: user.id,
            firstName: user.firstName,
            lastName: user.lastName,
            email: user.email,
        }
    })
    // column fields must match row fields, you can assign a header for each column and size if desired
    let columns = [
        {field: 'firstName', headerName: 'First Name', flex: 1},
        {field: 'lastName', headerName: 'Last Name', flex: 1},
        {field: 'email', headerName: 'Email', flex: 1},
    ];
return (
... 
) 
}


Enter fullscreen mode Exit fullscreen mode

Check your finished result, run npm run dev again if needed and you should have the exact same result.
Website with header DataGrid Component and green table in the middle, three columns for First Name, Last Name, and Email. Random sample data is included

Your code should now match that of the Master branch on the Github repo. If you are having difficulties refer to the master branch.

Conclusion

Material UI DataGrid gives you quick access to sorting, filtering, pagination, toolbar, searching, and so much more. Remix can be combined with DataGrid to instantly fetch and render data in a DataGrid providing lightning fast data grids. It only take a few quick changes to begin pulling in the data in Remix from another source and rendering that content in the rows.

I do hope that you find the tutorial useful, share it with your circle on social media! I'd like to hear any feedback, comments, criticism, suggestions, etc. that you can offer.

Top comments (1)

Collapse
 
alexserver profile image
Alejandro Gomez • Edited

nice, but this only covers the entry level dealing with client rendering,
did you have anyt trouble trying to do server site rendering with emotion cache when hydrating the app ?