Introduction for React Developers
hey everyone I hope you're doing well. I am here today hopefully to give you a high level overview of what a Elixir code base looks like. And I'm going to do this overview from a react developer perspective, so I'm going to give a bunch of examples uh to react and hopefully this is useful to you.
So let's start here. I have a clone of of my site project called Techschool.dev. If you don't know what it is just type on your browser Techschool.dev and you're going to find out. So on a Elixir code base, you can see here my face is in the front. Okay, but now I'm inverted anyways.
Elixir Project Structure: Lib Folder
Uh, on Elixir code base, the most important part of your code is going to be under the lib folder. And on the lib folder, you can see that there is uh the name of your project, a folder with that name, and then another folder with the name of your project underscore web. So the name of my project is tech_school, I have a folder called tech_school and another tech_school_web.
Business Logic vs. Web Logic
And as you can imagine, uh the backend logic, the business logic is inside the tech_school folder and then the UI/web logic is on the tech_school_web uh folder. I'm going to give just a quick overview of the tech_school folder, but I'm going to spend the majority of this video showing the web folder, which is the one that I'm going to talk about React, for example.
Business Logic Example: GitHub API Client
So on the tech_school folder, let me give you an example. I am calling the GitHub API to show the contributors of the project on the homepage. So interacting with the GitHub API is business logic, it's not UI logic. I'm going to display that on the front end later. So you can go here inside tech_school, I have a file called github.ex which stands for Elixir.
Modules, Functions, and Caching
Okay, now I need to go back to my place. Hopefully here is fine. Okay, so I basically created a module under the tech_school uh parent module. So it's defmodule Techschool.GitHub. I have a constant here which is named base_url and I'm going to call that URL uh throughout the code. And then I have a bunch of functions here. I have one called get_contributors and then another two functions with a defp keyword. As you can imagine, def is the definition of a function and then defp is the definition of a private function. So if I try to access the GitHub module outside of uh this module, I can only access the get_contributors. So the get_contributors what it does is — and this code doesn't look really beautiful, if you know how to refractor it, if you have more experience on Elixir, please let me know. Basically, I am checking if I'm running the tests. If I'm running the tests, I don't want to—I don't care about the GitHub API, I'm going to return an empty array. And here you have implicit return, you don't need to type return, you can just type an empty array, for example.
And if I'm not running tests, I am, first of all, trying to get the cache for GitHub contributors. And Cachex is a library that works on top of a native Elixir caching mechanism that uses the memory. So there's no Redis or anything on this codebase at all, it's just using in-memory cache. And the cache library works on top of the Erlang memory cache. Anyways, there's no, I just wanted to say that there's no Redis. Then I check if there is a cache. If there is a cache miss, then I'm going to fetch the GitHub contributors calling the API and then populate the cache. And if there is a cache hit, I'm just going to return the contributors. Right?
Connecting Logic to the LiveView UI
This is an example of business logic that you can find on Elixir. Now let me show you where I'm using this. If we go back to the tech_school_web folder, uh as I said before, I'm using LiveView for the front end. So the homepage is a LiveView, which is under the live folder. You click on live, I have PageLive. I use this name for like uh static pages like the homepage. So you open up that folder. I'm a front-end developer, so I need to break everything into smaller components, that's why I have a components folder.
So here we have two files, this is interesting. We have home.ex and this is where your logic for the homepage lives. And I could render the entire homepage inside this file, but I like separating UI from custom logic. So if you name, uh, if you use the same name for your page but using the .html.heex uh syntax, this is basically the render function that you could be using inside the home file, but you're using it separately. So yeah, uh Elixir does some magic behind the scenes to sync these two files.
Asynchronous Data Loading in LiveView
So if you open, if you open the code to the homepage, you need to scroll down a lot here. Let me see. Okay, uh the code doesn't look really good here, but it's because I'm doing an async_assign to the GitHub contributors because like, maybe the GitHub API is slow to respond. And I am using caching to mitigate that, but I don't know, if for some reason it takes a long time to get the GitHub contributors, uh, I don't want that possibility to happen on my website. So I am doing a first render of the page and then assigning later the GitHub contributors through an async_assign. If you worked with Remix for example, that would be the equivalent of me uh returning the defer function where you will wait for every single other promise, but you don't await for the GitHub API. So you defer that promise to the front end. This is basically what I'm doing here.
Calling Business Logic from the View
And if you go back to the home uh file, you can see that uh yeah, during the mount of the homepage, I am doing an async_assign to the GitHub contributors, and here I am calling the GitHub context. So you can see that I just typed GitHub.get_contributors, and then I'm using alias on top to avoid having to write Techschool.GitHub here, I just write GitHub.get_contributors. I'm doing an async_assign which is the equivalent of the defer on Remix for example. And then once uh the github_contributors variable is okay and there are results, then I display the content. That's pretty much what I'm doing. And then after that, I'm assigning the GitHub contributors to this variable and then looping over the github_contributors.result on the homepage. That's pretty much it.
A More Complex Example: Interactive Search Page
But now we're going to take a look at another folder where I'm rendering the courses page. And this one is interesting because if you go over to Tech School and my memory is not so good right now, I'm going to clean the SSD later. If you go to the courses page, here is a more interesting page. You have a bunch of filters. You have a search uh input. So I can type for Elixir here and there you go, I find the website and a bunch of courses. This is a more interesting page and I'm using live view, so this is where I want to show you how similar this looks to React for example.
LiveView Components and Typed Props
If you go to the course_live folder, you go here, you have the same uh logic of having the name of your file .ex for the logic and then the name of the file .html.heex for your UI. So the UI for the courses page is here and then sort of the JavaScript functions of your page are on the index.ex.
So yeah, let me zoom out a little bit further. This is something else that I wanted to show. Here you can see a bunch of @ everywhere. Do you know what that is? I am defining three components for this page. If you open the components folder, I have three components, one called CourseCard, another PlatformCard, and another for Search. I can define the props for those uh components here. And I can define the prop type for each uh for each prop of the component. So here, for example, I have a CourseCard. I'm expecting a course and it is required. So if I go to the front end, uh let me find a course card here. It is. This is the syntax of using a custom component. On React you would call the component name with uh uppercase on the first letter. On Elixir you call the name of your component with a dot in the beginning. So I'm doing a loop here over the courses and as I said, the course prop is mandatory. If I remove here course, I should get an error. There we go. I mean, not an error, I get an a warning. If you hover over the mouse here you can see 'missing required attribute course', which is pretty neat. I am a front end developer, this is very important to me.
Prop Type Validation in Components
Okay, same for any other component. So I have a search and I I have a bunch of uh props here. For example, language_names is a list and it is required. If I go back to my search component, which is this one on top, if I remove uh language_names for example, oops, let me remove that, uh I should be getting a warning. There you go, language_names. But if I have the prop here but it's the incorrect uh type, so I just say language_names={false}, I should get another warning. And there you go. If I hover over here, uh the language_names should be a list and I got false. So I mean, this is pretty much TypeScript for me. This is heaven. I freaking love this. This was one of the reasons why I picked uh Elixir uh for my side projects uh programming language because it's freaking amazing and the front end is awesome. So I can define the props, I can define the prop types, I can define if it's required or not. It's pretty, pretty neat.
LiveView Lifecycle and Event Handling
So how do I do the search here? I have a mount function that runs once to mount the page, which is very similar how React works. This would be the equivalent of a useEffect with an empty dependency array, so it's a useEffect that only runs once. And then I have another one called handle_params, which is triggered whenever — I might be wrong here, let me just read the doc — uh invoked after mount and whenever there is a live_patch event. So this also runs once, at least once, once uh like after the page is mounted, but then whenever there's a patch event of some sorts, uh this handle_params function is triggered again. So if you go back to the UI, take a look here. I'm going to open up the search component. On the search component I have a form, right? And then on the form I have a phx-submit event. I also have a phx-change event. What this does is basically whenever there's a submit on this form or a change, I am going to trigger the search. Okay? And there's a bunch of other primitives here. I also have a phx-debounce of blur to like, only trigger the change whenever there's a blur effect. Like whenever I click inside the search or outside the search, you have a lot of control here.
Handling Events and Updating the URL
But once I trigger the search event, what is going to happen? If you go back to my index.ex file, there is another function called, oh yeah, I have two events. One to load more courses, which is this button here. Let me clear the filters, I'm going to clear this up. If I scroll down, there's the load more button. Whenever I click on it, I trigger the load-more event. Um so I have two handle_event functions which are LiveView specific, one to handle the load-more event and the other one to handle the search event. So if you take a look at the search event, this one is a easier to understand in my opinion. I'm doing a push to the to the same LiveView saying that I changed the URL parameters. And I have another custom function here called build_url where I build the URL depending of which input got selected, what you typed uh on the search bar. So if you go back to the website, uh if I search for new, I don't know, uh new, no, let me search for Phoenix. Okay, you can see that the URL changed. Now I have a parameter called search and the value is phoenix. This is what I'm doing with the push_patch. Uh I'm doing a push_patch to a new page, I mean the same page but with URL parameters. On this case I can have a search parameter, I can have a framework parameter, language, tool, fundamental. And then once I add those parameters to the page, this second function called handle_params is triggered. And this is where I handle my uh this is where I interact with the business logic. This is where I go here and I'm like, okay, I need to search again for the courses, search again for the platforms. I have a couple of extra variables here to see if there are courses available, if there aren't then I'm going to do something else on the front end. It's pretty neat.
Why Phoenix LiveView Feels Like React
So this is pretty much it. Like the small overview of how uh Elixir and Phoenix, they work together, how you can work with the front end. I know I haven't covered anything about functional programming, how you need to like, uh do use this bunch of weird pipes, uh and then return the same socket at the end of the all the operations on the LiveView, but I just wanted to give you a quick taste of what Elixir looks like. In my opinion, this is the language and this is the front end framework that is most similar to React. I tried writing a bunch of other frameworks. I tried writing uh StimulusJS, Hotwire, uh I forgot the name of the other one, AlpineJS, but they don't look like React in my opinion. And then when I see this code, I cannot explain why, but it's similar. Like my React brain can sort of understand what's going on here. On a React codebase for example, we would have a function called onLoadMore, onSearch, and then we would call the backend or interact with the database. This is pretty much what I'm doing. The only difference is a little bit of the syntax because JavaScript is object oriented and Elixir is functional programming. So you need to do the weird pipes and then return uh the socket on every operation. But these are the small details.
Conclusion and Further Resources
If you enjoyed what you were seeing here and you're like, wow, this is this looks promising, I I like the front end, I like the back end code, it looks beautiful. If you are interested, then make sure you visit techschool.dev. This resource is 100% free. There is not a single thing here that is paid. The only thing you can do if you want is sponsor me. If you don't want to sponsor me, no problem. Just keep using the website, everything's free. Feel free to visit the Bootcamps tab, click on Full-stack Elixir and Phoenix. If you already know HTML, CSS, JavaScript, you can go, you can scroll down and click on Elixir. I have a bunch of cool recommendations for Elixir courses and Phoenix courses. So there you go. I hope you enjoyed this video and there's a bunch of extra Elixir content incoming. That's it, thank you so much. See you next time.