react-resource-view

Introduction

One declaration, five views, and a URL that carries the state.

react-resource-view renders the CRUD surface of a resource: the list and its layouts, the detail page, the create and edit forms, the delete confirmation, the filter bar and the pagination. You describe the resource; it writes the screens.

It is built on react-data-form for everything with fields in it, which is why the two are documented side by side.

One declaration#

articles.ts
import { createViewResource, tableViewOptionFactory } from "react-resource-view"

export const articles = createViewResource("articles", {
  name: "Articles",
  path: "/api/articles",
  view: {
    // The fields are the form *and* the table's columns.
    form: {
      inputs: {
        title: { label: "Title", required: true },
        author: { label: "Author" },
        status: { label: "Status", controller: SelectInputController, valueOptions: STATUSES },
      },
    },
    formFilter: { inputs: { title: { label: "Search a title" } } },
    viewVariants: [tableViewOptionFactory(), cardViewOptionFactory({ grid: 3 })],
  },
})

Rendering it is one component:

import { ViewResourceContextProvider } from "react-resource-view"
import { ActionList } from "react-data-form"

<ViewResourceContextProvider
  resource={articles}
  resourceAction={ActionList.list}
/>

What that gives you#

Everything below comes from a declaration of that shape — no screen was written by hand. Switch the layout, filter the list, open a row, edit it, delete it. A layout the package does not ship is one command away — create your own view variant.

A resource, running

No server behind this page

A resource declared without a path falls back to a localStorage-backed repository. Every demo on this site runs against a real repository with no API behind it — your edits survive a reload.

The URL is the state#

Which view, which item, which filters, which page, which layout: all of it lives in the address bar rather than in component state.

  • A link reopens exactly what the sender was looking at.
  • The back button does what the reader expects.
  • A reload does not lose the filters — which is the difference between a list people use and a list people fight.

Two routing modes carry it: in the path, or entirely in the query string for statically hosted or embedded views.

What it does not do#

  • It has no router. Four primitives are asked for; an adapter for TanStack Router ships with the package.
  • It knows no API in particular. Which backend answers, and how it spells a page or a filter, is a dialect — API Platform, Strapi and Supabase ship with the package — configured separately through configureApi.
  • It is not an admin panel. There is no generated dashboard and no scaffolding step: it is a set of components you render where you want them.
  • It does not own your layout. A view is a component, not a page.

Where to go next#

Other projects#

  • React Data Form — the form library this package renders its fields with, documented on this same site and published separately as react-data-form.
  • cardona.digital — the portfolio of Salvador Cardona, who writes and maintains both packages.