A small project listing pokemons with their specific details using the full stack web framework Remix.
- Every day a new JavaScript framework is born. But not all should be taken seriously as they lack community support and expertise. Remix is created by the team behind React Router and tries to innovate into the direction of Server Side Rendering (SSR) and is a direct competitor to Next.js and Gatsby all building on top of React.js
- In general the trend of modern JavaScript frameworks right now is going back to the PHP way of handling more frontend related stuff on the server. Remix offers only Server Side Rendering (SSR) and not Static Site Generation (SSG) or Incremental Site Rendering (ISR) thus is pivots away from the JAM Stack that got popular during the last years
- JAM Stack apps are really fast in their rendering and are easy to deploy since there are only static files. They have their problems handling dynamic data as the page needs to be rebuild on change
- Server Side Rendering (SSR) apps require a backend server to deliver the application. It is quite fast and handles dynamic data very well. The deployment on the other hand is more complex
- So Remix should be great for bigger applications that have many pages and handle dynamic data that origins in a form of database
- Works like in Next.Js file-based. Each folder within
app/routes
creates a route. The index.tsx file within it is the main route likeapp/routes/pokemon
would beexample.com/pokemon
- Remix offers a new thing called Nested Routes. When a route is nested under a parent the child automatically inherit the UI of the parent. In page a Router
<Oulet />
is defined. This Outlet will be replaced wth a child component based on the url you navigate to. When there is thepokemon(index.tsx
directory and there is another file calledapp/routes/pokemon/details.tsx
within it. If a user goes toexample.com/pokemon
the index.tsx will be rendered but if a user goes toexample.com/pokemon/details
the details.tsx file will be rendered to the same Outlet. This feature allows developer to defined child nested routes and only require them to think about one small part of the UI and not the whole subpage. Error messages no longer have to affect the whole ui page but can be on a component level. So B2B plattforms or dashboards can benefit from this a lot. - To opt out of Nested Routing for individual pages the file can be placed outside of a page directory and called with periods like this
pokemon.details.stats.tsx
. - Dynamic Routes are files with a $ sign before it like
$id.tsx
- Any Remix page can return a regular React Component but can also contain a loaderFunction that will only be executed on the server side and can bring in data into the Remix App securely. This is similar to
getServerSideProps
in Next.Js - While in Next.Js the data is provided as Props to the React component here in Remix the
useLoaderData()
hook can be used to load the server side fetched data. Remix polyfills the server side to allow the fetch() Browser API command within the server side code. - For writing data to the backend Remix also innovates. Instead of using the
onSubmit
event and usingevent.preventDefault()
on the handling function, in Remix you can use theForm
component that handles posting like a regular old html form like this
<form method="post">
<input name="foo" type="text" />
<input name="bar" type="text" />
</form>
So there is no more need to preventDefault here. But an action function on the server side is needed. This function has access to the values within the form by their name like this
export let action: ActionFunction = async ({ request }) => { let formData =
await request.formData(); let foo = formData.get("foo"); let bar =
formData.get("bar); // Update your database here return redirect("/your-path");
}
This action response can then be accessed within the frontend UI with the useActionData<string>()
hook. The useTransition()
hook allows access to the state of the action and reducing asynchronicity problems.
- This approach can the data flow within the application more easy for the developer
- Using the Remix
useFetcher
hook fetched data can be turned into a form. Then this form can be mapped to an action like a backend api ofpokemon-search.tsx
in this case.
- Installation with
npx create-remix@latest
. Here the remix app server was used. - Installing TailwindCSS with
npm install tailwindcss @tailwindcss/aspect-ratio @tailwindcss/forms @heroicons/react concurrently
- After that TailwindCSS needs to be configured through the
/config/tailwind.js
file. - Replace the
build
anddev
command within thepackage.json
with:
"build": "tailwindcss --output ./app/styles/tailwind.css --config ./config/tailwind.js --minify && remix build",
"dev": "concurrently \"npm:dev:tailwind\" \"npm:dev:web\"",
"dev:tailwind": "tailwindcss --output ./app/styles/tailwind.css --config ./config/tailwind.js --watch",
"dev:web": "remix dev",
- Next on head into
/app/routes/root.tsx
and addimport tailwindUrl from "~/styles/tailwind.css";
and remove the remixStyle imports to use TailwindCSS. Then edit theLinksFunction
like this:
export let links: LinksFunction = () => {
return [{ rel: "stylesheet", href: tailwindUrl }];
};