How to render a table from Sanity using portabletext/react.

7 replies
Last updated: Aug 31, 2022
Hi everyone, I want to render a table from sanity using portabletext/react but I don't know how to do that. Please what do I do?
AI Update

To render a table from Sanity using @portabletext/react, you'll need to use the sanity-plugin-table plugin to create tables in your Sanity Studio, then create a custom component to render them in React.

Important Note

⚠️ The sanity-plugin-table only works with Studio v2, which is deprecated. You should migrate to Studio v3 when possible. The plugin has a significant limitation: table cells only support plain strings, not rich text.

Setup Process

1. Install the Plugin (Studio v2)

# Using yarn
yarn add sanity-plugin-table@studio-v2

# Or using Sanity CLI
sanity install table

2. Add Table to Your Schema

In your schema, add the table type to your block content array:

{
  name: "body",
  title: "Body",
  type: "array",
  of: [
    {
      type: "block",
    },
    {
      type: "table", // Add this
    },
  ],
}

3. Create a Custom Serializer for React

When rendering with @portabletext/react, you need to define a custom component for the table type:

import { PortableText } from '@portabletext/react'

const components = {
  types: {
    table: ({ value }) => {
      const { rows } = value
      return (
        <table>
          <tbody>
            {rows.map((row, rowIndex) => (
              <tr key={rowIndex}>
                {row.cells.map((cell, cellIndex) => (
                  <td key={cellIndex}>{cell}</td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      )
    }
  }
}

// Use it in your component
<PortableText value={content} components={components} />

Alternative Approach

Given the limitations of the table plugin, many developers prefer creating arrays of objects to represent tabular data, then handling the table rendering on the frontend. This approach gives you more flexibility and allows for complex data structures within cells.

For more details on custom serializers and rendering Portable Text, check out the Presenting Portable Text guide in the Sanity documentation.

Hey there! Have you already added the table schema to your portable text?
The table is part of a sanity rich text field, I have already defined how to render the image, but I don't know how to render a table
user M
Got it. Let me see if I can find an example of a serializer for this.
user D
you can create a
Table
component like so:
const Table = ({value}) => {
    return (
      <table>
        {value.rows.map(row =>
          <TableRow row={row} />)}
      </table>
    )
  }
Then create a
TableRow
component:
const TableRow = ({row}) => {
    return (
      <tr>{row.cells.map(cell =>
        <td>{cell}</td>)}</tr>
    )
  }
Then add both of those to your
components
object:
const components = {
    types: {
      table: Table,
      tableRow: TableRow,
      // any other types you want to define
    },
  }
And finally pass that
components
object to your
PortableText
component like so:
<PortableText
  components={components}
  value={_rawField}        
/>
user X
Ok I'll try this now, thank you
One thing about Luke’s approach is that it’s not accessible at all. Someone using an assistive technology such as a screen-reader will not be able to navigate the content because this table doesn’t contain any header.
Maybe something like this:
function BlockTable(props) {
  const [head, ...rows] = props.value.rows
  const isBiDirectional = head.cells[0].length === 0

  return (
    <table>
      <thead>
        <tr>
          {head.cells.map(cell => (
            <th key={cell}>{cell}</th>
          ))}
        </tr>
      </thead>
      <tbody>
        {rows.map((row, index) => (
          <tr key={index}>
            {row.cells.map((cell, index) => {
              const Component = isBiDirectional && index === 0 ? 'th' : 'td'
              return <Component>{cell}</Component>
            })}
          </tr>
        ))}
      </tbody>
    </table>
  )
}

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?