DEV Community

Cover image for Remix: Something different
Andrew Bone
Andrew Bone

Posted on

Remix: Something different

Coming up to three years ago I made the shift away from web development as a hobby to web development as a job. Part of finding the confidence to do that was the learning in public I did here, on dev, so in that same vein I'm going to try my hand at learning remix.

Before I get started I should say I'm a front end developer with very minor back end experience. I've used NodeJS before and I've dabbled with PHP and Perl. Also I know NextJS is quite popular and may have even been a better choice to start with but I decided to see what Remix had to offer. I may look at NextJS in the future we'll see how this goes.

I'm going to be following the Blog tutorial on the Remix website, at least to start with. If I get to a place where I feel things are making sense I may stop following it and see where I end up. Now, without further ado, here we go.

The setup

Well first things first let’s make a place for us to do the work. I made a new folder called remix-server, though the name isn't important, and opened VSCode. In the terminal I entered npx create-remix@latest and followed the instructions.

Need to install the following packages:
  create-remix@latest
Ok to proceed? (y)

R E M I X

💿 Welcome to Remix! Let’s get you set up with a new project.

? Where would you like to create your app? .
? Where do you want to deploy? Choose Remix if you’re unsure, it’s easy to change deployment targets. Remix App Server
? TypeScript or JavaScript? TypeScript       
? Do you want me to run `npm install`? Yes

> postinstall
> remix setup node

Successfully setup Remix for node.
Enter fullscreen mode Exit fullscreen mode

When it asked where I wanted to create the app I just used . as that means here, had I wanted to make a new directory I could have written the directory name there like .\my-dir.

You may also have noticed I'm using Typescript rather than JavaScript, this is because I'm learning Typescript anyway but if you want to use JS that's fine most of what we write will be transferable, I'm sure.

Once NPM had done its thing I was able to run npm run dev and look at the server.

Remix default screen

Making routes

If we look a the files that have been created you'll noticed we have a folder called app and inside it another folder called routes in which there is a single file called index.tsx, a tsx file is a typescript react file you might see jsx which is the js equivalent. I had a look inside the index file and saw it was a normal looking react file that contained the contents of the demo page we'd just made.

Reading ahead in the tutorial we see it wants us to modify the index file and make a new route so let's do that but also let's deviate from the script just enough to make sure we know what's going on.

I plan to amend the index file to contain a Link as it says to do in the tutorial but then I will make a new directory called test and inside it I will put a file called index and another called inner. I posit I will then be able to got to localhost:3000, localhost:3000/test and localhost:3000/test/inner to see my 3 files.

/* base level index */
import { Link } from "remix";

export default function Index() {
  return (
    <>
      <h1>This is a test</h1>
      <Link to="/test">Test page</Link>
    </>
  );
}

/* Index file inside '/test' */
import { Link } from "remix";

export default function TestIndex() {
  return (
    <>
      <h1>This is a test</h1>
      <Link to="/test/inner">Test inner</Link>
    </>
  );
}

/* File called inner inside '/test' */
export default function Inner() {
  return (
    <>
      <h1>You found me!!</h1>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

And what do you know it works. It seems any directory inside the routes folder becomes a route, if an index file is inside the route it is served when you go to the route directly and any other files can be reached by typing their name after the route in the URL. I'm sure there will be more complexity than this further down the road but that seems to be a good enough understanding for now.

Let's get on with the tutorial.

Getting data

This section feels a little messy to me, it starts by having you put all your code in a single file then tells you this isn't best practice and has you refactor it. Also, in the typescript version, it has you use type when a interface works perfectly well. I'm going to tell you what I did differently I don't think it will make a massive difference in the end but I feel it's less confusing this way.

useLoaderData hook

Firstly we need to use a hook called useLoaderData we import this from remix just like we did for link. This also requires us to have a function exported from the file we're using useLoaderData in called loader. It's best practice to make this function async as that allows us to wait for data to load. The loader function should return our data in the format we want to ue it in our react file.

import { useLoaderData } from "remix";

export const loader = async () => {
  return 'hello world';
};

export default function Posts() {
  const loadedData = useLoaderData();

  return (
    <>
      <h1>Posts!</h1>
      {loadedData}
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

This above snippet would print 'hello world' as loadedData would become what the loader function returns.

Now if we want to get more complex data from our loader it's a good idea to make a new file that contains the function, then import that function into our react file and use it inside the loader function. As we don't want this new file to have a route let's go back up to the app level and make a new folder called 'loaders' in here we'll make a file called posts.ts.

export interface Post {
  slug: string;
  title: string;
}

export const getPosts = (): Post[] => {
  return [
    {
      slug: "my-first-post",
      title: "My First Post",
    },
    {
      slug: "90s-mixtape",
      title: "A Mixtape I Made Just For You",
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

This file contains an interface that describes the data that getPosts returns. We also have a function called getPosts that simply returns the 'data' we want to get. In the future this could contain some database calls or something but let's keep it simple for now. Both the interface and function are exported so we can use that back in our posts index file.

import { Link, useLoaderData } from "remix";

import { getPosts, Post } from "~/loaders/post";

export const loader = async () => {
  return getPosts();
};

export default function Posts() {
  const posts = useLoaderData<Post[]>();

  return (
    <>
      <h1>Posts!</h1>
      {posts.map((post) => (
        <li key={post.slug}>
          <Link to={post.slug}>{post.title}</Link>
        </li>
      ))}
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

As you can see we're importing the interface and the function. The interface lets us modify the useLoaderData function which allows us to have auto complete in our IDE by saying the posts const is and array of Posts as described by the interface.

Dynamic routes

To add a dynamic route you make a new file in routes directory. The files has to start with a $ but the rest of the name can be anything you like. In the example given by remix they use slug so we'll do the same.

Something magical happens when you do this. The loader function from before can see the URL you've entered and do something with it but let's take a step back and understand what is going on here.

It turns out the loader function is always past an object that we can use. That object contains a request object, a context, which was undefined for me, and a params object. The request is the full request the server is receiving including the full URL, the method, GET in this case, and even a query which might come in handy later. But now we have a simple understanding of what the loader function can do let's carry on.

The part of the URL we care about is stored in the params part of loaders params and is called whatever the file is called minus the $, slug in our case.

export const loader: LoaderFunction = async ({params}) => {
  return params.slug;
};
Enter fullscreen mode Exit fullscreen mode

LoaderFunction is an type we imported from remix to keep typescript happy.

Loading data

We can use normal NodeJS things like fs to load in files from the file system. The tutorial has us create some markdown files out site of the app directory that we can load in.

Using fs we can get a list of all the filenames also we can load the post titles, which are inside the md, using parseFrontMatter. This data can be structured to replace the old static array of posts.

Now we need a new function that can take our slugs, from the dynamic route, and open the file to display the md as html. Once again we use fs to load the file then we use marked to convert the md to html. We call this function getPost and once we've imported it into our $slug file we're there.

Recapping

To recap we've,

  • started a new project using npm
  • made some custom routes
  • loaded some data to construct a dynamic list of content
  • read an md file and converted it to html
  • displayed that html in a dynamic route

That both feels like a lot but also hasn't felt like too much. We're only half way through the tutorial but this post is getting long so it feels like a good place to get off for now.

Thank you for reading it really means a lot. Please feel free to leave a comment even if it's to tell me what I've done wrong or what I can improve.

If you'd like to connect with me outside of Dev here are my twitter and linkedin come say hi 😊.

Discussion (6)

Collapse
link2twenty profile image
Andrew Bone Author

This is my first post in a while so but I was really inspired when listening to the dev discuss podcast that I had to learn something new and remix has been on my list for a while

Collapse
mrkyllers19 profile image
MrkYllers19

Hello sir, I want to ask, does being a web developer only require HTML, CSS, and JavaScript? Are there other languages? please reply sir

Collapse
link2twenty profile image
Andrew Bone Author

Hi, when it comes to web development there is the front end (the bit that runs in the browser) and the back end (the bit that runs on the server).

HTML, CSS and JS are a good starting point and can get you quite far. A good understanding of JS is required as a foundation for learning things like React, Vue or even just interacting with APIs.

As for the back end there are a whole host of languages you can use like PHP, Perl, Ruby or even JS (through node).

TypesScript is like JavaScript but has a few variations to make it more strict, it also needs to be compiled before it can run in the browser.

TLDR; HTML, CSS and JS are crucial for front end or full stack development but are the foundation.

Thread Thread
mrkyllers19 profile image
MrkYllers19

Thank sir 😊

Collapse
lico profile image
SeongKuk Han • Edited on

Remix, interesting. This is the freamwork thatvI've first heard. I should go check this out now! Thank you for sharing the post :)