Consuming a Rails API with a NextJs client
Tags: nextjs, ruby, react
Published: 2022-11-28 13:08:20


>  **tl;dr;** Previously [here](https://dev.to/raphox/rails-7-hotwire-turbo-stimulus-modern-web-applications-4o7a), I wrote about how to write a modern web application using Rails as a full-stack framework. Just writing HTML and Vanilla Javascript. Now we will go ahead creating a React client App using NextJs.

The existing API has the following endpoints:

    GET /api/kit/products(.:format)
    POST /api/kit/products(.:format)
    GET /api/kit/products/:id(.:format)
    PATCH /api/kit/products/:id(.:format)
    PUT /api/kit/products/:id(.:format)
    DELETE /api/kit/products/:id(.:format)

In the new project, we have the same screen as before:

![In addition, the screen lists all products, a form filter, and a form to create and manage the products.](https://cdn-images-1.medium.com/max/2000/0*-ot83FVW5ubYvwwJ.png)

We have a lot of customized components:

    src/components/
    ├── Form
    │   ├── Actions.tsx
    │   ├── Input.tsx
    │   └── index.tsx
    ├── Layout
    │   ├── Page.tsx
    │   ├── Sidebar.tsx
    │   └── index.tsx
    ├── Loading.tsx
    ├── LoadingOverlay.tsx
    ├── Notification.tsx
    ├── Products
    │   ├── Form.tsx
    │   └── Sidebar.tsx
    └── SearchList
        ├── Form.tsx
        ├── ListItem.tsx
        └── index.tsx

But our pages are simple and short. For example, take a look at the products page code:
{% gist https://gist.github.com/raphox/2ea13127a5b72a268a7550eff2609732.js %}

## Highlights

###[NextJs](https://nextjs.org/) is just a choice, not a requirement

The API made using Ruby on Rails is completely independent of the Next JS client application developed with NextJs. You could use any RESTfull client application to consume the existing API.
In my [project](https://github.com/raphox/rails-7-fullstack/tree/nextjs/frontend), I am using the NextJs project as a subfolder of my Rails repository, but you could put it anywhere.

###Why [Next JS](https://nextjs.org/)

I already worked with [React Router](https://reactrouter.com/) and [React Navigation](https://reactnavigation.org/), but when I knew the **[Next/Router](https://nextjs.org/docs/api-reference/next/router)** and all related features, as the **[Next/Link](https://nextjs.org/docs/api-reference/next/link)**, I loved it. We can use partial load and caches. Get more info [here](https://nextjs.org/docs/api-routes/introduction).

###Conventions

You can create your own convention for your own projects. But, in my opinion, it is beneficial to use a convention that is popular and validated in production by many other developers. Like Ruby on Rails, NextJs gives you a directory structure, core resources (link, routes, image, etc.) and rich documentation.

###[SSR](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props)

After to create a few projects using SPA, it doesn’t seem to me a good choice for big projects. So, for now, I am using [SSR](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props) with NextJs. The main use of SSR is to improve the SEO, but like this approach to offer the a better UX.

###[React Query](https://tanstack.com/query/) is the link between the Rails and NextJs

Working together with [Axios](https://axios-http.com/) ([my code](https://github.com/raphox/rails-7-fullstack/blob/nextjs/frontend/pages/kit/products/services.ts#L9-L41)), it is a great option to consume the REST API (and [GraphQL](https://tanstack.com/query/v4/docs/graphql)). You have the access to: isLoading, isError, data, error, and others. It is a very easy way to load data and rescue errors.
{% gist https://gist.github.com/raphox/0371794bab3f19eb04892e4d7c394d36.js %}

###[React Context](https://reactjs.org/docs/context.html)

I don’t like [https://react-redux.js.org/](https://react-redux.js.org/), it brings a complexity to the project that I don’t think soo is a good thing. But we can use the React Context and React Reducer to offer a store and events to manager states of the application. You can see the it on the project here [https://github.com/raphox/rails-7-fullstack/tree/nextjs/frontend/src/contexts/products](https://github.com/raphox/rails-7-fullstack/tree/nextjs/frontend/src/contexts/products).
In my code, I am using a context to share the state between different components on the same screen. The Form component is able to update the product item in the sidebar list.
The **React Query** also uses a context and we can exchange states between them. After updating a product, we can trigger changes to the product list.
{% gist https://gist.github.com/raphox/39716829aefca7951ef86ea64078a714 %}


###React components with namespace

It is something that I learned recently. I used it in my project to offer a way to override children of some components and prevent to set many properties throth the parent. Like in the following code:
{% gist https://gist.github.com/raphox/f9fbbcdd186c9d0ed4e9bb3fb47cf1d6.js %}
In the previous code, we have the namespace *SidebarPrimitive* with nested *Root*, *Header*, and *List* components. I am using the *Root* component to wrap the content and I am passing the *props* to the respected child.

###[Tailwind](https://tailwindcss.com/)

There are controversies related to it, but trust me, create a project using it and make sure that you don’t like or love it.

## Dependencies:

* [https://tailwindcss.com/](https://tailwindcss.com/) “Tailwind CSS works by scanning all of your HTML files, JavaScript components, and any other templates for class names, generating the corresponding styles and then writing them to a static CSS file.”

* [https://www.radix-ui.com/docs/primitives/utilities/slot](https://www.radix-ui.com/docs/primitives/utilities/slot) “Merges its props onto its immediate child.”

* [https://tanstack.com/query/](https://tanstack.com/query/) “Powerful asynchronous state management for TS/JS, React, Solid, Vue and Svelte”

* [https://axios-http.com](https://axios-http.com/docs/intro)/ “Axios is a simple promise based HTTP client for the browser and node.js. Axios provides a simple to use library in a small package with a very extensible interface.”

* [https://github.com/lukeed/clsx](https://github.com/lukeed/clsx) “A tiny (228B) utility for constructing `className` strings conditionally.”

* [https://lodash.com/](https://lodash.com/) “A modern JavaScript utility library delivering modularity, performance & extras.”

* [https://react-hook-form.com/](https://react-hook-form.com/) “Performant, flexible and extensible forms with easy-to-use validation”

* [https://github.com/jquense/yup](https://github.com/jquense/yup) “Yup is a schema builder for runtime value parsing and validation. Define a schema, transform a value to match, assert the shape of an existing value, or both.”

## The project
**[rails-7-fullstack/frontend at nextjs · raphox/rails-7-fullstack](https://github.com/raphox/rails-7-fullstack/tree/nextjs/frontend)**

## External references:

* [https://www.typescriptlang.org/](https://www.typescriptlang.org/)

* [https://www.radix-ui.com](https://www.radix-ui.com/docs/primitives/utilities/slot)

* [https://reactjs.org/docs/context.html](https://reactjs.org/docs/context.html)

* [https://medium.com/@kunukn_95852/react-components-with-namespace-f3d169feaf91](https://medium.com/@kunukn_95852/react-components-with-namespace-f3d169feaf91)