Writing modern React apps (w/ Redux Toolkit + Typescript + Material UI + Auth0) | David Armendáriz | Skillshare

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Building a VS Code clone with React (w/ Redux Toolkit + Typescript + Material UI + Auth0)

teacher avatar David Armendáriz, #NeverStopLearning

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

48 Lessons (6h 21m)
    • 1. Introduction

      2:16
    • 2. Defining the Code Editor App requirements

      3:03
    • 3. Installing NVM

      4:14
    • 4. Creating the boilerplate code

      5:35
    • 5. Configuring Auth0

      9:01
    • 6. Creating AuthProvider Component

      7:59
    • 7. Adding Material UI And Loading Component

      5:05
    • 8. Adding ProtectedRoute Component

      4:24
    • 9. Creating CustomThemeProvider Component

      9:52
    • 10. Setting Up Routes

      8:16
    • 11. SignIn And SignOut Buttons

      8:10
    • 12. Building Header Component

      12:18
    • 13. Building Layout Component

      3:38
    • 14. Building Home Page

      10:28
    • 15. Adding Programming Languages Icons

      4:30
    • 16. Adding CodeEditor as a Protected Route

      5:01
    • 17. Introduction to Redux

      9:33
    • 18. Writing DarkMode Slice

      10:19
    • 19. Tests For DarkMode Slice

      4:08
    • 20. Configuring The Store

      9:03
    • 21. Typing Redux Hooks

      7:37
    • 22. Action Creators vs Actions

      2:32
    • 23. Implementing Dark Mode

      10:54
    • 24. Configuring Persistence

      13:16
    • 25. Creating Files Slice

      8:36
    • 26. Creating Files Reducers Logic

      8:22
    • 27. Adding Tests For Files Reducers Part 1

      9:21
    • 28. Adding Tests For Files Reducers Part 2

      3:38
    • 29. Adding SelectActiveFiles Selector

      20:48
    • 30. Adding ReadFile Function

      9:34
    • 31. Understanding FileViewerStructure Type

      6:02
    • 32. Creating OpenFile Thunk

      9:15
    • 33. Adding Tests For OpenFile Thunk

      7:51
    • 34. Creating CloseFile Thunk

      7:30
    • 35. Adding Tests For CloseFile Thunk

      8:23
    • 36. Creating ReadFiles Thunk

      5:23
    • 37. Adding Tests For ReadFiles Thunk

      11:27
    • 38. Adding Tests For SelectTreeViewData

      10:24
    • 39. Adding SelectTreeViewData Selector

      9:42
    • 40. Adding OpenWorkspace Button

      11:27
    • 41. Adding ExtensionIcon Component

      3:53
    • 42. Creating FileViewer Component

      12:41
    • 43. Added Custom Editor

      13:04
    • 44. Added Custom Tab Panel Component

      5:16
    • 45. Added Custom Tab Label Component

      8:04
    • 46. Added CodeEditorContainer Component

      11:53
    • 47. Added CodeEditor Page Component

      6:56
    • 48. Conclusion

      0:42
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

223

Students

--

Projects

About This Class

UPDATE: this course has been re-recorded to provide the best audio/video quality and to update Material UI updates (v5 had breaking changes)

UPDATE: source code for this course: https://github.com/DavidArmendariz/code-editor-app-course-v2

In this course, you will learn how to build a simple yet complex app (a code editor in the browser). You will learn a lot of things from such a simple project:

  1. React with Typescript
  2. React best practices
  3. Redux
  4. Redux Toolkit
  5. Material UI
  6. Testing
  7. Docker
  8. Authentication with Auth0
  9. Protecting routes with React Router Dom and Auth0
  10. Implementing dark mode

At the end of this course, you will be able to transfer all the knowledge you will get to a real world application. You can also take this project as a portfolio project. It contains lots of things that you would use in a big React application.

Meet Your Teacher

Teacher Profile Image

David Armendáriz

#NeverStopLearning

Teacher

Hi! I am David Armendáriz and I am an ecuadorian mathematician. I like everything related to Data Science and also I like to apply my knowledge in this topic to software.

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Introduction: Hi, my name is Debbie them and that is, and I am a software engineer and mathematician. In this course, we will be building modern React apps with TypeScript, with a redox toolkit of 0, material, UI, et cetera. So what we will be learning in this course are the following things. React with TypeScript react this practices redox, redox toolkit material UI testing with just Docker, authentication without 0, protecting routes with React router dominance 0, and implementing dark mode in our app. So this course is intended for beginners and intermediate React developers. Understanding of JavaScript and a basic understanding of redox is necessary. What to expect from this course. At the end of this course, you will be building a complex app while learning advanced concepts from reflux that you can use in a big project. You can also learn how TypeScript and helped to reduce bugs. You can also expect to learn how to manage authentication with alpha 0, specifically with the React SDK, I'm learned how to test some of the business logic of your app destructor of this course. We will rebuilding the app by parts. Thus, we will be building these up component by component in an order fashion. For example, we're going to focus on how to build the file viewer component, how to build the store, then configure it, how to build as lysis of the store and things like this. So we will be taking these order approach in order to build the app. So without further ado, see you in the next lecture, and I hope you enjoy this course. Bye bye. 2. Defining the Code Editor App requirements: Hi and welcome back. So now we're going to learn, while we're going to build, we're going to build to code editor app. So something like VSCode. But in the browser. And these are their parliaments of their app. First, we need authentication. So when the app starts, we shall see homepage. And the homepage, there should be a nav bar that has the title of the app and interact a login button. The login button should lead us authenticate using Google or some other methods like e-mail and password. If we authenticate successfully, we shall be read directed to a protected route where the code editor app will be accessible. Once in India, never, the login button should now be the login button. And if we click on this button, we should return to the homepage. Then for the code editor app itself, first, we will need a file explorer. So the actual half a tree-based file and directory Explorer. Given a directory as an input, it will show all the files and folder within the directory, including sub folders, obviously, all directories. She'll be in the collapsed state, an application load, but can then be expanded and collapsed by clicking on them. Directories and files. She'll have icons. Now, the editor itself, the app needs to have a code editor based on the Monaco code editor. Each file should open a new tab and we should be able to close the gaps. When we double-click a file in the file explorer, initial openness, a new tab in the code editor. So if you don't know what the Monaco code editor is, let's see. Let's search for this on Google and see the definition of it. So the Monaco editor is a code editor that powers Viscoat. A good page describing the code eight or feature is here. So you can click on there. And well, this is basically the code Ager, so we're going to have these in the browser basically. Okay. What else? The code editor app also needs a Workspace button, so an open workspace button. So when we are inside the code editor, a button shall be shown in enough fiber. And by clicking on this button, we should open a dialogue box that lets us select Add Directory. Finally, there are some non-explicit requirements. For example, when a reloading our files shall not be clear. That means there should be some kind of births systems in the app. For now, these are the requirements. See you in the next lecture. Bye bye. 3. Installing NVM: Hi and welcome back. So now that you have all the advantages and disadvantages of using windows, Let's go to the next point, which is node version manager. So obviously this is a NodeJS course, so we need node. And there are two ways of installing node. The first one is going to know G as an org. And here clicking on these long-term support version, or you want to use the latest, latest version with the latest features. You can click on here. Okay? And that will install Node.js on your machine. But I don't recommend this because if you are working on multiple projects, maybe you're taking another NodeJS. And NodeJS course has an older or newer version, I don't know. And you want to switch between these two classes, then you won't be able to do that because you have a stick with just one version of those. So in order to have multiple versions of nodes, there comes nvm, which is not personal manager. And in the about page it says, as you can see, and VM is Version Manager for Nadia, be installed per user and in both PowerShell, and then works in any POSIX compliant shell. In particular on these platforms, Unix, Mac OS, and Windows Subsystem for Linux. So it doesn't say Windows, it says Windows Subsystem for Linux. That's why I insist so much. You install Windows Subsystem for Linux. Again, if you don't do that, I won't be able to help you with the installation. Although there exists this NBN Windows, think. But again, this is complicated. Your self unnecessarily just install Windows Subsystem for Linux. Then you have to run this command. Again. You are using the ASH or OMICS age instead of bash. Then just replace this with TSH and then you are good to go. Okay, so if I open my terminal here and I type nvm, as you can see, I already copied and pasted this command. That's why I can use the npm command right here. So if I type nvm, this is going to show me all of the options I have available. And it's very, very easy to install versions of node, as you can see here. Just type npm install and the Persian, and that's it. And here, if you want to installed the latest, Well, not, not the latest, but a long-term support version. Just type npm install dash, dash LDS, and that's it. This is 14.17.4. I already installed it. That's why it says that this is already installed. And it's saying now using this version of nodes is you want to see all of the Persians available or the versions that you haven't sold type npm list. And here you can see I have this 14.17.114.17.4. And this arrow tells me that, hey, I am using this version 14.17% for right now. If you just want to display the version without one of these things, then just type npm current and it's going to show you the version. Okay? What else can I tell you if you want to use the other version, just type npm use and the other version. And there you have it. Okay, so it's very, very easy to NPM. There's no rocket science on this. Okay? And that's it. That's it for this video. Just one more thing. Executing this command is just going to put this script inside. In my case, it's going to be that CS HRC. Your case probably is going to be badger, see, if you are using Bash and so on. So that's it for this video. I hope you like it. See you in the next lecture. Bye bye. 4. Creating the boilerplate code: Hi and welcome back. So now we're going to start with some boilerplate code. So first of all, let's make sure that we installed the LTS version of node. I already have it installed. So probably if you didn't have the LTS version, It's gonna take some time for you to install it. Then to use it. Just say npm is no. Okay, now let's run this command and px Create React app, then the name of the project. And we're going to say my code editor. And then dash, dash template. And let's specify here that we want to use TypeScript. Okay, so it's going to take some time for these to create. So I'm just going to pause the video here and resume when this is finished. Cool, So everything went good. So now let's see the code editor. And here I'm just going to open VS Code. And it opened in my second window. So I'm going to drag it here. Okay, So here we're going to do for changes before we start coding. So the first one, if I type nvm current here, it says 14.17.1, we want to keep consistency in which version of n nodes, sorry, we're using. So for that, I'm going to create this nvm RC file. And here I'm just going to put 14.18, which remember is the version we use to create these react project. Okay, so now if I type in the console nvm, then it's going to start using version 14.18, the one specified in this file. It has found the NBA MRC pile with the version 14.18. I type nvm current, It's going to show that version. Okay? The second thing that I want to put here is prettier RC file. This preacher ossifies, going to allow us to configure the rules for preach here to format our code. And by the way, if you didn't have preacher, you can go to Extensions and search for preacher. And here installed the first option, and you're good to go. This is going to allow you to start formatting your code automatically. Okay, so here I'm just going to specify some rules. You can modify them if you want. It's up to you entirely. So I'm going to say that I always want to use semicolon. I always wanted to use single quotes. Print width. I want it to be 120. And if you hover, it's going to say the line length we're preacher will try graph. Okay, so that's basically all the options that I'm going to put here. Nothing too fancy. So the third thing I wanted to do, I don't know why, but when you create a React project with Create React app, it adds these deaf dependencies, dependencies. So this testing laboratory testing library is types just love of law. And TypeScript also is also a dev dependency. So let's create a new depth dependency section here. And let's put all of these things inside dev dependencies and TypeScript as well. Okay, so now we have correctly the dependencies and the deaf dependencies. And last but not least, I want to configure Ts country. So here you can see in the documentation from TypeScript, TypeScript line.org, this config there you can see all of the functions of these properties here. And there are good defaults, so I'm not going to change them, but I want to add something else here. And that is the base URL. And I'm going to set it to source. So this basically is going to allow me to use absolute imports. What does that mean? So if I go here to, for example, app.js x, and suppose I have a component like for example, button from and I have the components in a very, very subtle like this here, like that. So instead of doing this nasty thing, we're just going to get rid of all these dots here and say components button. And that is an absolute import. Okay, So in order to do that, we need to configure that base URL in the compiler options. So that's everything for this video. Hope you like it. See you in the next lecture. Bye bye. 5. Configuring Auth0: Hi and welcome back. So now we're going to configure of 0, which is pretty easy. We just have to follow documentation. So if you go to google.com, then go to login or sign up. And then well, if you already have an account with an e-mail address and put it here, I'm going to create one with Google, with my Google account. I'm just going to continue with Google. Okay. So now this is the first page that you're going to see. You can choose the tenant domain to be whatever you want. For example, you can put my code editor if it's available. I don't think it's available. Okay. Or just stay with default one that they give you here. I'm just going to stay with the default. Again, I'm going to create an account here. Great. And wait for this to load. And okay, so this is the dashboard for office 0. Then go here to applications, and let's create a new application. So here you can choose single page web application and you can change the name of your app if you want. I'm going to stay with the defaults. Right? Now here in the QuickStart, you can choose react, and you can follow the documentation here. I'm just going to make your life easier. And let's go to Settings. And we're going to, we're going to copy this domain and this client ID. Okay, so let's go and here inside the root project, let's create a dot ENV file, and also let's create a sample file. Okay, so here inside that, well, first of all, let's put them in there. A gitignore. So here I'm going to say that in that in the direct sample, that is not going to be in the gitignore, that that can be committed to the repo safely. Okay, so here I'm just going to say React app, client ID. And let me copy and paste this. And here instead of plants, I'm going to say domain. So this envy direct sample, as the name suggests, is just an example. It's not going to contain the actual piece that we need for our React app to run. This is just for other developers. So they can see and say, Hey, I need these things in order to start my app in local development. But these dot ENV file, this is the one that is going to actually have the keys for our reactor. So that's why I put dissident be inside the git ignore so it cannot be committed to our wrap-up. Okay, Um, so let's go again to our Dashboard and let's copy this domain. Reset here. Inside that dot ENV. I'm going to put the main to be this. Let's put it inside quotes just in case. And let's copy the client ID. And again, in quotes, you can protect client ID. Okay, so that's everything we need from for our environment variables. But if we go to Quick Start, Let's go and choose react here. And yeah, get your application keys. We already did that. We got that the mean and the client. And the other thing that we need to do is to configure the callback URL, D logout URL, and the allowed web origins. So we take a quick look here. It says the callback URL is a URL in your application where all your red Directory user, after they have authenticated the callback URL for your atlas be added to the allowed callback URLs field in your obligation settings. And if this field is not set, users will be unable to lugging to the application and we will get an error. Okay? And the logout URL is a URL in your application that officer can return to after the user has been logged out. So basically the same thing is for logging in and logging out. And as well, we need these allowed web. Okay, so let's go to Settings. Let's go to where is it allowed, callback URLs. And let's say http localhost 3000. And I'm going to also set the 1000 one because, you know, sometimes I have. Port occupied. So maybe I want to use port 3000 one, the same thing here, and the same thing here. So these three things are needed. And then you go to the bottom of this page and save the changes. Okay, so that's everything we need here. Okay? And if we go here than we already added that logout and Kohlberg URLs, the allowed web origins. Now it's time to install the 0 react as decane. Okay, so that's what we're going to do in the next video. Before doing that, we're going to actually start creating something here. Inside source. I'm going to create a folder called conflict. Okay? And inside this conflict, I'm just going to create an index.js file. And what I like to do here is to export an object. We're going to export default and object. And I'm going to centralize here all of my environment variables. So I'm going to see say officer domain is going to process that, that react to your domain. Okay, so remember this one. And if this is not set, then I'm just going to prove that default value here. I'm just going to put an empty string. But if you are, for example, working in a company be probably can expose some default value for this. And also, I'm going to say our client ID. And we're going to process that and react tab of 0 client that. And again, I'm going to default this to an empty string. Again, maybe they have a secure default value for this, but right now I'm just going to default it to an empty string. So why I'm doing this? Well, this is a good choice for when you want to centralize your environment Bibles. Suppose that you have a very complicated environment Bible. I have seen that case in the past. Complicated environment Bible. So maybe you need a function, get Process Environment Bible. And you call a function process and complicated and variable. And by doing these there you have, then you have a single source of truth of doing all of these things in order to get them centralized here. And then in your code you simply call this thing here. And here you can extract the necessary environment variable that you will use in your code. So that's the whole purpose of this object. And this is a good practice that I wanted to teach you. And yeah, that's it. That's basically it for four days. These are the only environment bubbles that we're going to use throughout the code. So that's it for this video. Hope you like it. See you in the next lecture. Bye bye. 6. Creating AuthProvider Component: Hi and welcome back. So now that we have set up everything correctly, not 0, then the next step is to use the React as decay. So here we need to install all zeros lash of your react. So let's do exactly that. Npm install 0 of 0 react. In the meantime, I'm going to show you the guide that we're going to use in order to create our authentication related components. So for example, here we have these auth provider with history, which is the one that we're going to basically copy. And this is basically these, but using the history from React router them. And that made me remember that we also need to install React Rotterdam and types react Rotterdam as we are using TypeScript again. So let's go here. And in the meantime, let's create inside the source folder called off. We're going to handle components that are related to authentication. So the first component is going to be the provider, the TSX, because we're using TypeScript. And here I'm going to use this snippet. So you don't know what this year is, is basically just typing these. And it generates, it generates some run random useful boilerplate in order to create components. So in order to get the snippet, you need install the ES 7 React redux, GraphQL, React Native snippets. So by installing these, then you can type that. I just did rough. Meaning react arrow function. Remember a function components? Yeah. So yeah, this is going to create these boilerplate for you. So the first thing that we're going to import here is not react. By the way, if you didn't know, React is not mandatory to import scenes, I think versions 17 or maybe 16. I don't remember. But you can't amine reacting part if you want. So prompts with children is going to be a type. Let's see what. So it's a type which accepts a P, which means basically any other type. And in this symbol here means intersection with these children, which is optional. And this is of type react nodes or undefined because it's optional. So yeah, that's the first thing. And that is going to be the type of our props, props with children. And we need to supply the additional prompts, or remember this p here inside this curly bracket, sorry. So here we're just going to say NT uptick because we're not going to pass any other properties to these auth provider. Okay? So that's the first thing. The second thing, basically we're just going to copy and paste this thing here. Okay? So let's copy and paste. Basically everything. We're going to replace this domain and client IDs. So don't worry. Okay, So we have, we need to get these provider from provider from your reactants. Okay? And these domain and client ID, yeah, we're going to get them from the conflict folder, important conflict from config. So we're going to see conflict that your domain. And we're going to get the client ID from that client that we don't need this audience here. And the children is going to come from props that children, okay? And yeah, we need also use history hook. Let's get rid of this thing here. And this is history. Hook basically returns the history object. So if you want to learn more about the history object, go to react router.com slash web slash, api slash history. And here you're going to get a brief introduction of what the history object is. So basically, this allows us to navigate the user with this push method or Blaze, go back or forward, center, etc. It also lets us return the location. And the location is an object. And you can get from that object that pathname, the search, which is basically the URL query string, a hash, a state, tetra, etc. Yeah, basically this history object is going to be the browser history. There also exists this hash history and memory history. But we're not going to take a look at these things. Are going to use the browser history, which is basically, as it says here, Dan, specific implementation useful in web browsers that support the HTML5 history API. Hash history is for legacy web browsers and memory history is an in-memory history implementation, useful, interesting and non-dot environments like React, Native. Okay, so we're going to use the browser history. Undoubtedly. So let's get the history from that's imported from router. Us history rate. And these apps that is used is on rhetoric callback. First, let's see what our rhetoric callback is. Or is it search on rhetoric callback? So here, as you can see, it says method to handle the event. We're off here, redirects your users from the office 0 universal login page to your React application. You use US history hook to get the history object from React router and the history that push method to take users back to the route. Dean tended to access before authentication. So in our case, that route that they intended to access before authentication is going to be the code editor route. Okay, So this is an app state. And if we go back here to our rhetoric callback, this accepts a callback with App State, which has this abstract type. So we can search your upstate. And it's going to be important from zeros slash officer react. So that's cool because now we have everything typed with TypeScript, so everything should work correctly now. So that's basically what we're going to do in this video. I hope you like it. See you in the next lecture. Bye bye. 7. Adding Material UI And Loading Component: Okay, so before we move on with the other author related component that I wanted to create for this course. We're going to solve material UI, the UI framework that we're going to use in this course. And they actually recently changed to the version 5. So they introduced the lots and lots of breaking changes. And that's basically the reason I am rerecording this course to show you how to deal with these new changes. So first of all, we need to install material UI. I'm going just to copy and paste this in here. And install on a gel. You eyes slash material, emotion, react, motion style. So day completely changed the way they style things. So that's basically why they broke the course, basically the last version of this course. And well, I'm going to take advantage here. And I'm just going to say that we are going to use this towel components for this course. So we're going to also need to install these two things. And maturely you asked as C, which means some components and style components itself. So let's copy this thing. And PM saw these two things. And yeah, so you can search here in the documentation. These selection, we're going to simply, we're going to create a simple loader, which is going to be basically returning component from Julia. I think it was called linear progress. No link, no linear progress. Yeah, this one. So basically we are going to This thing here. We're going to create a new folder inside source called components and sub-components. I'm going to create a new folder called common. Okay, because this loading components going to be commonly used by many other components. So I'm going to say New Folder loading. And this is the convention that we're going to use. For folders. We're going to use kebab case. And for the components we're going to use, the first letter is going to be capitalized. And then it's going to be geoscience actually. And it's going to be the same name of the folder, but with the first letter capitalized. So why we're going to do this? Well, in a large-scale project, probably you're not going to only have loading the TSX, but you're going to have tests for this loading that TSX, maybe utilities related to this name here. Or maybe if you are using COPD, CSS, you're going to have some flu-like loading the model dot SCSS. And probably you're also going to have loading dot test that sank. In this course. We're not going to concentrate too much on testing components, but the logic behind the complaints. So, but this is going to appear in a large-scale application if it's well architected and things like that. And if you are going to use SAS with a scope, CSS, that means CSS modules. And you're also going to have broadly this structure here. So that's why I am doing during following this pattern. It's not that I want to complicate my life more that some comments I have received in the past for this course. This is the real reason I am doing this. Okay, So here I'm just going to import linear progress from material, UI material. And basically I'm just going to return that thing here. Linear progress. Again, why am, and why I'm doing this? Well, basically, because I want to have a commonplace where if I want to modify all of the loading components throughout all of the app and I just have to modified here, I'm nowhere else. Okay, so that's basically we have installed material, you have created loading component that is going to be, it's going to be widely used in the app. And that's it for this video. Hope you like it. See you in the next lecture. Bye bye. 8. Adding ProtectedRoute Component: Hi and welcome back. Now that we have sorted out how to install material you how to create a login component. We're going to finish our work with. Authentication. Components may create just another component related to authentication, which is going to be called protected route. So these protected a route component is going to be used to protect the route as the name says. And basically we're going to just let's see, let's, yeah, here you can see protecting routes. And this gives us an example. Hopefully. If I scroll down here, it gives us an example of how to do this. Again. So we're basically going to copy and paste this example here. So let's do it. Yeah, we're going to all these things. But here in loading, we're going to get that from components slash slash loading, slash loading. Okay? And here we need to provide some types for the prompts that we're going to pass to this. So basically we're going to say type, protect the route for ops. And this is going to be, this is going to have a component which is of type component as the name suggests. So this the only thing we're going to get from React. And the other thing that we are going to get is basically keys string type any. So basically anything here. And this is going to be type of is protected route prompts. Component is going to be of type component and the rest is going to be whatever. So basically this means whatever. Okay, So I think we need anything else here to do. So basically this is going to get the route or yeah, we need to, Let's see, module has exported member. Okay, so let's see, we have a problem here. I don't think we have a problem. Yeah, this is a default exports. Sorry. So that's why I was having this problem here. Yes. So basically, what this is telling us is that we're going to pass to this protected route, are going to pass a component. And the rest of the arguments that this route, this route prop, gaps. And we're going to pass that route. But with a component, we're going to use these with authentication required, which is something from 0, 0. And as you can see here in the description, when you wrap your components in these higher order components and an anonymous user visits your components, they will be redirected to the login page and returned to their page. They were red director read directed from after login. Okay. So basically, this is going to help us to throw you unauthenticated users to the login page. Okay. So yeah. And when they are read directing, we're going to load this loading components. And that's it. That's everything we need to protect a route. That's why our makes our life easier. Because we have things like this with authentication required, higher-order components that allows us to do the heavy lifting for us. Okay. So that's it for this video. Hope you like it. See you in the next lecture. Bye bye. 9. Creating CustomThemeProvider Component: Hi and welcome back. So we have created our authentication related components. Now it start and it's time to start building the app. And for that, we're going to need lots of styling and material you are fortunately, helps us with providing a common theme throughout the app, through the create function. So instead source, I'm going to create a theme folder. And here I'm going to create a color start ts file and also a Gustaf Theme provider dot TSX file. Okay, let me use this snippet to create all of these boilerplate code. And inside the colors that we're going to export three things. We're going to export the common colors, the lag colors, and the dark mode colors. So let's start by doing that. We're just going to define constants here. So common colors is going to be wide. And it's going to be this thing here. Blank is going to be okay. And the tip. Then we're going to say light colors, going to be apprenticed, say background's going to be common colors that white, the font is going to be common colors, that black. And the primary colors going to be this color here that I just made up, which is 20, 30, 40. Let's see. And for the dark colors are just going to say font is going to be common colors that wide. So the inverse, now it's not going to be black but white. The background split here, like this. Background's going to be this other color that I found, which is 23. Okay? So these are the colors that we are going to use in our app. As you can see, they are not many. So now let's try to guess what we're going to do here. So first of all, this is a provider's, so this is going to receive, as props, we're going to save prompts with children. Okay? And here I'm just going to as an empty object. So profit is only going to have children optionally. And let me get rid of this thing here. Again. So what we're going to return is a beam provider and that is a component that is from Joel UI. So if we import from arterial slashes styles, then from here we're going to import to things actually create theme and the theme provider. Okay? So we're going to return actually a theme provider. And here we, sorry. Here we need to close the thing. We need to pass the children prompts the children. Okay. And this is red because it says property theme is missing and type blah, blah, blah. So we need to also pass a theme here. So that's what we're going to, next. We're going to say const, going to be equal to create theme again. And as you can see here in the documentation, it says, it takes an incomplete theme object and add the missing parts and generate a theme based on the options received. So it returns a complete ready-to-use theme object. Okay, So you can see in the documentation of the things that you can passing this object. For example, we have the police. And the police can have these mode. And here we can specify the mode, dark or light. So actually we need dark mode Bible. And this is going, we're going to get these rival firm redox. But right now we didn't have any store set up. So I'm just going to say that this is going to be false. When we set up the redox store, we're going to change this. And well, here we can say dark mode is true, then use dark. Otherwise, use the light mode again. And we can also say primary color to be made. Actually here, let's Is this primary to be in the common colors like that? And in main I can say ABC colors. Important thing, important. Maybe colors. Colors. We're going to say colors that actually we need to import this as like this. Common colors. Trolls with my keyword come colors that primary. That's what I wanted to. Again. So we have the lead, we have specified the mode and the primary color. And here now we can pass the theme to be that. Okay, but we are not done yet. Why? Well, we want to specify additional properties here. So for example, I want to specify background. Depending on the dark mode. If it is true, I want a dark mood. Colors actually are polars and also like colors. So if these true, I want dark, dark colors, background. Otherwise, I want light colors, that background. And in the font, depending. If dark mode is true or not, I want dark colors, that font. Otherwise I want light colors and fonts like that. And also I want to include the common colors as well. All the common colors object. Why not? And right now it is complaining and saying that the argument backgrounds, this background, fun and common colors are not allowed. So let's look at the documentation. Same material UI react, theming, shirtless. So as you can see here. Okay, so this is what I'm basically doing, custom variables. And it says if you are using TypeScript, you will also need these module augmentation for the theme to accept that both values. So basically we have to declare this module. Let's copy this thing here. Okay, let's spread here. Okay? So here in the theme, we need to add these things here. So let's add them here as well as here. Remove this comment. And obviously we need to pass the correct options here. So for the background it's going to be strained. Say string. For the font against string. And for the common colors, it's going to be an object where the key can be string and the value is going to string. So let's just stop him, paste this below, and the error is gone. So now any component of our app is going to have access to this theme and also to the background, font and the common colors. So that's pretty cool. Also, depending if the dark mode is on, these background and font colors are going to be set automatically. Okay, So that's all for this video. Hope you like it. See you in the next lecture. Bye bye. 10. Setting Up Routes: Hi and welcome back. So we have done lots of things right now. So let's start by creating our routing system. So we can start creating our pages. And remember, we're going to have two pages, the homepage and also that code editor, which is going to be behind the protected route components. Okay, So let's start by removing things that we're not going to need. And those things include the app dot, css and amp up. Here, Let's delete this thing. And let's go and also delete the logo. We're going to need that. Okay, we're not going to need any of these imports right now. We're not going to need any of these code here. And well, first of all, we need the browser history to be available to all components, right? So if you remember in the documentation we have that the browser history is useful in web browser that support the HTML5 history API. Has She's 34 legacy web browsers and memory for NANDA environments like React Native. Okay, and remember that our auth provider, that history objects. So go to all of the provider. This uses the history object. So we need these to be available in our components. So it's pretty easy. We just need to import browser router from React router done. And people tend to import these as rudder. I don't know where that convention came from, but that's the convention to report that as a rudder. Ok. So everything that is a child of this router component is going to have the history object available. So that includes the provider, the provider, okay? And we also need to wrap all of our components in the custom theme provider. So we're going to do that. And yeah, so inside the channel of this thing here needs to be the routes. So for that, we're going to start creating our routes. So let's create the new folder called router. And that router is going to have two files. The first one is going to be pads that and this is going to be simply an object that is going to have all of our pants. So I'm going to export default and object. The first bad is going to be the home, and it's going to be just slash. So that's why it's going to be the homepage. And the second path is contributed code editor, which is going to be slash code dash. So I'm just going to declare all of the path of my application here. These are only, these are the two things that we're going to have here. It seems that we're not going to do much, but believe me, you are going to do a lot here. Well, the other components or file is going to be the routes that TSX. And again, I'm going to use my snippets here. Okay? So here we need to refactor these in the future because we're going to use lazy loading. We're going to also uses the current pages. We wouldn't have any page right now. So we're just going to test these with simple task components. So first of all, weren't going to replace this with a string. So let's import switch from React router. And this basically allows us to determine which rod we're trying to access. So inside the switch, we need to declare our routes. So we need to also import route. So the route, I'm just going to create a publicly available routes. And this is going to be exact so it needs to match the band that we're going to provide here. And this path is going to be provided by that object back home. And we need to pass a component. We can either pass it as a child of these routes components or we can pass it as a problem. I'm going to pass it as a problem just to keep consistency with what we're going to do next. Well, I can already tell you why why I'm passing this as a component. Remember here in the protected routes were patting also this is broken. So I'm going to also pass these abrupt for publicly available routes. So we need to balance the component. We didn't have any yet. So I'm just going to say cause. And here, I'm just going to say, I'm going to return the same helloworld. And I'm just going to pass it like this. Okay? So as I said, we're going to need we're going to need to refactor these in the future. But we can already start testing this. But first, let's import that routes component here. So like this. Okay. Okay, so let's, let's run npm start. And that's okay. We have some warnings here. They are. Lint warnings are important, no anonymous default export. And it says, Sign, object to a variable before exporting as module default. In country.csv config index.js. So it doesn't like that I export these object like this. So just to get the rate of these warnings, let's do it like this. Let's save and export. Default. Config again. And the same with bats, that doesn't like this. So let's do an export default bad. Okay? So probably that is linked role doesn't like that because it's easier for some intelligence tools to determine that this is bad. And maybe that's the reason. Because if you have an export default, then the object doesn't know it doesn't, it doesn't have a way to assign it a name. And probably for debugging purposes and intelligence tools, it's not a good choice. So yeah, that's a small detail. Now let's go to here, localhost 3000. And as you can see, we have that Hello World in place. Okay, So that's everything. For now. In the next video, we're going to start creating the layout. And the layout, pretty simple, but the complicated part of this layout is going to be the header. Okay? So the header is going to contain the sign-in, sign-out bottom. Some other buttons that we're going to see and the need to be shown conditionally if we are we are signing were ventilated or not. So yeah, that's why we're going to do next. And yeah, I hope you liked this video. See you in the next lecture. Bye bye. 11. SignIn And SignOut Buttons: Hi and welcome back. So it's time to start creating our pages. But before doing that, we actually need to create the layout and the layer that is going to be something very simple. It's just going to contain a header and the content of the page. So we need to create the header and that is going to take us some time. So my doing that weren't going to have the sign-in button, the sign-up button. We're going to have other buttons that are going to be useful as well. So let's start by doing that. Inside components common, I created these empty folder called header. And we're going to start with the sign and the sign up button. So let's create Sign In button. And I'm going to use my snippet here to generate all of these boilerplate code. And as I told you earlier, Our going to use material UI version 5. So that's one of the reasons I am re-recording this course because it's actually a breaking change. They introduce lots of breaking changes. And one of those breaking changes our styles, everything related to stars here. So I just wanted to show you how it's done. The material you UI version five way. Okay. So first of all, let's import this button here. This comes from material. And I'm going to import this thing called a style from material UI slash materials is lifestyles. Okay? So this is how you create a static component. You will sign in a name like sign out button, style, and you pass the first the component that you want to style. And then you pass here a arrow function. And the first parameter, the only parameter of this function is going to be, and I'm going to deconstruct this object to have the thing. Okay? So I'm just going to return an object from this arrow function. And the subjects are, disability contains the CSS properties that we are going to use. And well, here I am, I'm going to use the properties that you're going to declare here are actually going to be like JavaScript properties, not CSS properties. So that's the difference between normal style components and material UI component, material you, I saw components, sorry. So for example, instead of doing some like, I don't know, I guess you can do it. I'm not sure really. Text-align. Instead of doing that, we're going to do some text-align, some like this. So note that we're using CamelCase here. Well, in normal CSS, you can use calories, you use a kebab case. So in this case, I'm just going to set a color, the color of the text of the button. And I'm going to say theme, that common colors, that white. So remember in our custom theme provided provider, sorry, we declared these common colors property. So we don't have, we don't have to import the Color subject directly. So that's cool because now we have, we can call this common colors directly from theme. Again, now we're just going to say that the color of this button text, not the background, but the text of this button is going to be white. Okay, So we didn't have to hard code the white color here are our things like that. Okay, so I think that's pretty cool. Now we just need to use this. Actually this is sine style button. So sign in style button. And here we just use these as if it were a normal buttons or it going to sign-in. And we need to pass the onclick handler. So that's actually going to be pretty straightforward. We're just going to use the use of Hook, use of 0. And here we can, we can get lots of things. Actually. One of those things is login with pop-up or login with re-direct. I'm just going to say login with re-direct to see the universal login page. And if you go here to the function definition, you're going these accepts optionally an options object. And these options object, the type is rhetoric login options. So let's see what this here is. So this extends from baseline in options. So everything here is going to also be included here. And these are just some additional properties like the redirect URI, the apostate, the fragment. So I'm just going to set the upper state. Remember, if we go to the auth provider on the on-ramp direct callback intercepts an apostate. And if this apostate contains this returned to property, then we're going to use in order to push the history, which an element into the history stack. So sprayC, we're just going to say on sine is going to be logging in with rhetoric. And we're going to pass an object at a state with this return to property, which is going to be bad. Remember that path object dot code editor. So when we sign in, we're going to get the user to that location. And obviously we need to pass the onclick handler here. Okay, so we pass this function there. So that's it for the sign-in button. Now let's go to the sign-up button, which is going to be pretty, pretty similar. But just copy, paste, changed the name to sign out button. Okay, so I'm just going to change the name of this thing. So probably as these two things are equal, like sign-in and final buttons, probably we can move this to a component, to its own component. But right now we're not going to adapt. Okay, We're just going to maintain this. Got changed. The sign out again. And this should be on sign-out. And instead of using login with either act, we're just going to use a logout, which is another function. Okay? So we go to the function definition. It accept these options object is logout options and we have the return to property client ID, federated local only. We're just going to specify these returned to property. Okay, so let's go and let's just Live from here to here. And return to, it's going to be the window, that location. Are you. Okay? So basically where we're seeing a thorough us throw us to the homepage. That is the origin. Okay. So when pads here and yeah, that's basically it for the sign out and sign in button. So I hope you like it. See you in the next lecture. Bye bye. 12. Building Header Component: Hi and welcome back. So last time we created the sign-in and sign out button, Let's create yet another button, which is going to be the button that is going to allow us to go to the code editor up if we are already signed. Okay, so let's go here and let's go to the code editor, button dot TSX. Okay, and actually, let's just copy and paste everything here is going to be a very, very easy button. So let's go here and change the name of this thing. Again, we can refactor this later and make this a common button. So let's call it like this and everything should stay the same. And here, we're just going to change this to onclick. We didn't need these use of 0 anymore. So this is important is not going to be needed. Again, this is not going to be needed. And we are going to change the name of these texts to be the code editor. So when we click on this button, we want to go to the code editor. So we need to use the history object. So let's go and get the history with the US history book. Okay? And basically we're just going to say history dot push. And we're going to say Pat, code editor. Okay, and that's it. But well, let us start creating the header itself, which is going to be like the container for all of these buttons. Okay, So let's create the header that TSX, right? Lads, put boilerplate code. And here the first thing that we are going to do is to import, not react. And we're going to form up bar from material. It's going to be AB bar. We're also going to use toolbar and also topography. Okay? So the app bar is just going to be the navbar header or whatever you want to call it. So let's use that component here. Bar. Okay, well, we can go to the documentation AB bar material UI to see how this is used. Okay, we click here merely.com slash components, the slash app bar. And here you have all of the examples where you can use this thing here. So this is how you use it. You have lots of examples here. Okay? So let's start using these in our component. So we're going to say this is going to be positioned relative. If you want to change that, you can do it. Horse and C, We are going to include the toolbar. And the first thing that we want to do here is to put a topography. And that topography is going to be the title number up, something like that. And at the same time is going to be a link to the homepage. So let's go to Type. And again, you can search for the options that we can pass through these things. You can either go to the documentation on or you can click on here and see in the code what are the things that you can pass to this thing here? I think in this case it's probably easier to go to the documentation. You can go to typography. And here you have the topography API. Basically, this is a way to import it. And here you can say, Hey, you have these no rap paragraph as X variants are going to say the variants are going to set the variant to H6. And we're going to use these f x property. So let me explain what this thing, what this thing is. So remember here we have, we're styling our components like this or a sane styled with BAS name of the component. And we start specifying the properties. We can do the same but inside the component itself. So it's basically inline CSS, which by the way, it's not my favorite, favorite thing to do. But anyway, aids material UI, new, new way to do it. So I'm just going to teach you both ways. So this is basically like putting styles inside the components. So we can say flex one. And basically this is for taking most of the space under title. Okay? And in such here, I'm just going to mix things up and I'm going to say I'm going to create this file. So I'm going to say styled link. Be styled, which remember, we need to import from material UI, material styles. Okay, so we pass the name of the component, and this time is going to be a component from React router Tom. So let's import it into the link from React router Tom. Okay, so we're going to style this link so you can see we can style whatever, not necessarily a component from material UI, but it can be from another part. And here we're just going to say, give me the theme. And we're going to return an object, same text, decoration equal to none. Because we don't want that under, Underline for links. And we're going to say color is going to be the common colors that are white. So basically the text inside the link is going to be white. So now we can do exactly that. So we're going to see, are going to say a style link. And here we need to pass the place that we want to go. This is going to be pads that home. And we can put some text here. So the code editor app or something like that. And actually, yeah, we're going to see if this works. Probably we need to put this above the topography or the other way around. So when we render these and we can actually start the app and see this thing up working. We're going to see if it's correct or not. Okay? So we have now a title but useless right now. We need to do something else. We need to include the buttons that are going to be shown when the user is authenticated and authenticated. So let's start by writing here. Or if you want, you can write, get an r component, but I don't want to fill this with lots and lots of components. So here what I'm going to do is just say const on authenticated or unauthenticated bottles. So it's going to be just another component that we are not going to export. And let's see. Yeah, so here we're just going to return a div. And inside this div, we're going to basically render the Sign In button, okay, because when we are unauthenticated, we want to sign in, right? So let's do that. Sign bottom. Perfect. And we also need the authenticated buttons. So this is where things are going to get interesting. So let's see authenticated buttons. These buttons are going to be, that's returning this. Okay. Here I'm going to say, well, the sign, the sign, the sign out button, sign out. So let's see why this is not getting okay, so here I forgot to change the name of the components of the sign out button. And now it should appear here, sign-up button. Okay. Let's see. Yeah, it's scrapped. And then we're going to based on their location, we are render two buttons. But right now we're not going to do that because we don't have the other button that we have to include. That is basically the open workspace bottom. The open workspace Bollinger going to allow us to basically upload all the files. So right now I'm just going to, I'm just going to import this code editor button. Again. I think I didn't change the name of this theme of code editor button. Okay, Go code editor button. Let's see if this error goes away or not. Yeah, it goes away. Oh, and here it's actually the sign-in bottom. So I've mix things up very badly, but hopefully now it's everything is in place right now. Okay, so now we have for the unauthenticated buttons, we're going to have the sign-in button. And for the authentic eat bugs. And we're going to have the Code Editor button and the sign out button. Okay, so what's the next step? Well, it's pretty easy. We need to render these conditionals. So if we are authenticated, we're going to render this angular unauthenticated. We're going to render this. So let's do exactly that. Let's say const. We're going to use the use of book, okay? And this is going to return as the authenticated variable. And this is a Boolean. Basically it's telling, as you can see, some Booleans true or false. So below this, topography are going to say load is, we're going to say, if we are authenticated, this is true. Let's return the authenticate buttons. Otherwise, let's return the unauthenticated buttons, and that's it. So again, we're going to need to refactor components because we have a way right now to visualize this. And also, we need to include later on in the course, the street in order to get the dark mode on or off. But for now we are good with this. So in the next video, we're going to start building up the layout. So hope you liked this video. See you in the next lecture. 13. Building Layout Component: Hi and welcome back. So we are very close to start writing our homepage component. But before doing that, we still need to do some things. In common. We're going to create a layout which is going to be shared by both the code editor page and also the homepage. So let's create a new file called laid out that TSX. Going to put the boilerplate code. And let's start by importing the props with children type. So this is going to be props with children. And I'm going to pass an empty object because right now we're not going to pass any additional props to this layout component. Okay? So, yeah, Basically we're going right in other, some other style components. So we're going to use the style from maturely UIs slash style. Okay? So the first one is going to be the layout container, which is going to be a styled. And here comes the honeypots. Okay, we have seen how to style a component raw material. We have seen how to start a component from another library like Red Rock react Rotterdam. Now that we can feel mystyle components like this. So we just say here as a string and there we are. And this time we're not going to need any, any product from the theme. So we can simply pass an object. In the second column. I'm, I going to say, Hey, I want these to be 100% of height. And the wine, I want this to be display flex, and I want the flex direction to be column. We're going to see why in a moment. So we're going to replace this div with a layout container. Okay? So in these layered container, we're going to include the header, the header that we just created, either. And also we are going to inside another side component. Well, let's first grade that another style component. I'm going to name this page. And it's going to be styled. We're just going to say hi to 100% were wrong here in the CSS. We're going to correct it later when we can actually see this. So now I'm going to say page and we're going to render inside this page, props dot children. And that's it. That is going to be the layout a component. So anything that is passed in these layout component is going to have a lay-up container, the header and the content is going to be inside this page style component, which is just a div with high 100%. So we can occupy all of the height of the page. Okay, so that's it. That's basically, we're not going to do anything else here. Hope you liked this video. See you in the next lecture. Okay. 14. Building Home Page: Okay, so we are almost done. So let's create the new folder called pages. And inside pages, I'm going to just create a new folder called home. And inside this folder, I'm going to create the Han shot TSX component. Going to put the boilerplate code here. And let's start by importing that layout component. So this should be like this layout. Okay? So everything inside these layout is going to share that common layer that we just also, let's import the style because we're going to write to style components here. Materiel styles. Okay? So the first style component that we're going to create this the home container, which is going to be a style. Okay? Yeah, This time we're going to need the theme. And we aren't going to return an object. We're going to say display flex. We're going to say flex direction column are going to say, and we want a height 100%. We want to justify the content to the center. You want to align items to the center. And we want the background color to be a theme, that background. Okay? So remember this background is going to change whether we are, well, conditionally, if we are on dark mode or not. Right now we set the argument to false, but we're going to change that in the future. So we don't have to worry about that right now. Okay, So this is the first component. Let's add it here. Also. Home container like this. Like this. And inside the home container we're going to set or put another stock component. It's kinda be the welcome message style component. And this has been to espouse, going to be styled there. And again, we're going to need the theme here. Okay? I don't, we return an object with a padding of, let's say 15 pixels, a font size of 30 pixels. I know we're not making things responsive here. Okay? But these will, these will work right now. So we're going to have these CSS properties and we're going to include this here. Welcome message. And remember this is just a div. So we are going to say welcome to the code editor. And so, yeah, that's hidden that we have now something that will work. I also wanted to put another component here to make things right here that we're going to probably do that in the next lecture. For now, let's do actually two things. First thing is to change this test component with the home component. But here comes the part, the interesting part. So we're going to use something called lazy loading. So we're going to say sum like this, and I'm going to explain you these in a moment. Let me just write the same tax for it. Important pages. And that's important. React, react, react. Okay. So basically what this is telling to react is that we want to load this component just when we need them. Okay? Well, we have the code editor page. We're also going to do the same thing. So what is the purpose of why we're doing this? Well, when you're, the size of your application grows, then the bundle is going to grow as well. And we want to make this bundle as small as possible. And this is the easiest way of doing that by simply importing this JavaScript file just when we need them. Okay? So for example, if we're on the homepage, we're not going to load the code editor page and all of the dependencies of that page because we don't need that. We are in the homepage. But when we change to the code editor page, we're certainly going to need that. And that's when these import, which is a dynamic import, it's going to return us because this is a promise. Okay? So this basically callback that returns a promise. So this is basically a synchronous code. And talking about the synchronous code, what happens if this takes some time to load? We need a fallback for that case. So we can't let the user. Be waiting. If the thing is getting too long to process takes too long. So that's where the suspense components come in. And let's go to suspense. React. Actually. React. And it is suspense for that affection. I don't think this is what we need. In fact, I have never seen this. I have to take a look at it. And this is the one we want go to splitting. So as you can see, bundling mosaic tiles will have their files bundled using tools like webpack, ROLAP or procedure phi level of lamb. So here it says, bundling is great, but as your app grows, your bundle will grow to, especially if you are including large third-party libraries. You need to keep an eye on the code you're including in your bundles so that you don't accidentally, accidentally make it so large that your updates long time to load. So well, this is basically what I just told you. And this is a way of importing with a React lazy loading. We just did. And we need these suspense. Okay, let's see if we have here. Here is the explanation. It says the lazy components, you'll then be rendered inside of suspense component, which allows us to show back contact such as loading indicator while we're waiting for the lasing component to load. Okay. So yeah, this is what I was telling you. This returns a promise to import. So yeah, we basically need to put this code inside suspense. So that's what we're going to do right now. And in fact, I'm not going to do it inside the routes, but inside the app itself. Already said here. I'm going to put it here. It can actually be can be where wherever you want, provided. It's this is wrapped inside that. And why I'm putting this here and in app.js x, well, this also can, allows us for other things. So suspense component is not only useful for this, for rotting with lazy loading is useful for many other things. So probably you want that in your whole application. So fall back. I'm going to say it's going to be the loading component. Let's say loading here. And okay, so remember I mentioned is stupid third party libraries at the top, on our components at the bottom. Okay, so that's it. Let me see if we need we need to change this to be home and we are good to go, I think. Okay, so let's run npm start and see if this works correctly or not. Let's cross our fingers. And let's go to localhost 3000. Okay, So we have here the welcome to the code editor app. We have the sign-in button is code editor app, which is a link. Actually. We're going to test signing in and sign out when we have at least some test components. For the code editor page. Here. Let's inspect this thing here. So as you can see, this is not getting all of the height of the page, and that is because this route. So let me see if I can make this bigger. Okay? So this root doesn't take the whole page, and this body doesn't take a whole page, and these HTML doesn't take a whole page. So we need these three things to take the whole page, because this already did the whole pages. You can see here it has had 100%. So let's make that correction right now. Let's go to index.js. And let's say for HTML, for body and for the root identifier, we're going to say height 100%. And let's go back. And there we go. We have now these centered at y would have justify-content center and align items center. So this is centered basically. And yeah, that's it. We have to still add some other components to make this legal breach here. And then we're good to go work or we're going to digest authentication after doing this. So I hope you liked this video. See you in the next lecture. Bye bye. 15. Adding Programming Languages Icons: Hi and welcome back. So we have created the home component. It looks pretty now we're going to have an r component. And this is only for the creative purposes. So this is optional. What is not going to be optional? Are the assets that we're going to add. So let's create a new folder called assets. And inside here I'm just going to say images folder called images. And this is going to be attached to the lecture again, So and also to the repo. So I'm just going to copy and paste some these assets. And these are basically just SVGs. And while, yeah, yeah, They're only the logos of some of some programming languages, Sorry. So, yeah, we don't have a way to see this. Let's see if I can open the folder for images. Let's see. View my icons. Here they are. We have this blank file, this CSS3, go Lang, HTML, et cetera, et cetera. And XML has done programming language. But anyway, let's up this acid here, and let's go to component, and we're going to create a home component. And here I'm just going to create a programming languages list. And inside this folder, I'm going to see programming languages list that TSX, again, the boilerplate. And this time I'm just going to copy and paste what I have in my notes because it's a lot of repetitive code. So basically I'm just going to import all of those SVGs. So this is how you important React component as CSS icon or whatever you want to go icon, HTML icon, whatever these name is up to you from assets slash images, slash the name of the file. And then I'm going to put this thing here. So let me just copy and paste this thing here I have in my second monitor, like this. Okay, so we have rendered this as VGS. This is the way you can render as we use with Create React app. If you are not using Create React app, then probably it is not going to work for you. Okay? And here as you can see, I'm putting some inline style. So this is yet another way to put a style two components. This time, i'm, I'm doing it like this because I don't want to complicate my life more. So I'm just going to declare this style to be a JavaScript object to be padding 10 pixels, hi, 50 pixels, with 50 pixels. Okay? And again, this is not responsive enough, but it will work for now. So yeah. This is basically inland styling. It's not my favorite, but we're going to keep it like this for now. So yeah, that's it. Now, let's include this inside the home component. So this is going to actually be here. We're going to save programming languages lists. Okay? And well, we don't need to pass any children to this. So that's the only thing we're going to do here. And let's see what is the result. So yeah, it shows this pretty lists of programming languages. So we're going to say that we are going to support all of this programming language. So I think that's it for this video. I hope you like it. See you in the next lecture. Bye bye. 16. Adding CodeEditor as a Protected Route: Hi and welcome back. So it's time to test that our authentication E's working correctly. So I'm just going to create the inside pages in your folder called code editor. And here I'm just going to create a code editor, that TSX component. I'm going to use my snippet to generate all of that boilerplate code. And I'm going to let seem important the layout of one. And remember, we have this lab component are going to seem to test here because we're not going to write any code related to the code editor yet. Okay, so now we need to do actually two things. Well, first of all, let's go to the routes. And here I'm just going to say const code editor. And I'm going to say React dot lazy. And I'm going to form from pages or that into our code editor proponents. And now this good editor and needs to be a protected route. So I'm just going to import that protected routes. I'm going to say path, path anymore. And the component is going to be the code editor components. So as simple as that. So that's why I love it, because it makes things a lot more easier. Let's move this import the bomb here. Okay? So now these route is protected completely by 0. We didn't have to do anything else to protect that route. So let's test this. So we are in localhost 3000 and let's go to code editor and see what happens. Looks like. Yeah, So it looks like we need authentication in order to access this page. I'm just going to continue with the Google. Okay. Okay. And I didn't get prompted to select the email because I was already I already did that. So there are some cookies that avoid asking for your email again. But that's a small detail. Now we have access to this. If we go here, you can see that I can actually go to the homepage and I can go to the code editor and I can sign out and it's going to throw me to window.location origin. Now let's test the same thing, but by clicking on the sign-in button and clicking continue with Google. And there we go. So as you can see, there's like little instantaneous moment where we got the throne to the, to the homepage. And we can easily fix that by going by easing the East loading property from use of 0. So there's this is loading property which basically tells you if it's loading the information related to a 100 vacation. So basically it tells us if we are being authenticated or not. So let's move these like this. So while this thing is loading, are going to return the loading component, right? Loading components. And hopefully with this change, we're not going to that homepage for a millisecond or so. So let's test it. Has this again signing. Let's continue with Google. And there you go. You didn't see that. Let's do that again. I was distracted. Continue with Google. And yet I didn't see the homepage. So yeah. You can go here. Takes a moment on the way to go to the code editor, go back here. And as you can see, everything is working correctly and out. And I get thrown to the location origin. Okay, So that's it. I don't think we need to do anything else. As you can see, protected, Rob, protecting route with all 0s. So easy. And that's it for this video. I hope you like it. See you in the next lecture. Bye bye. 17. Introduction to Redux: Hi and welcome back. So we're going to start with probably the most complex part of the course. I don't know if it's redox or how the code editor itself. Yeah, I think it's rid x because it's going to contain all of the logic for the code contained to a torque properly. So many people have said that the find the redox part of the scores the most difficult part. And I understand because we are not learning a redox where learning redox toolkit, redox toolkit abstracts many of the ideas from redex. And I think it is good because it makes things simpler. But we have to have at least a basic understanding of redox. So in order for you to understand a redox perfectly, you just need this graph and you'd need to keep in mind the redux is just a library. But the idea behind Redux is these, these diagram here. So here we have, let's see, 1, 2, 3, 4, 5, 4-part that and are the fundamentals of the system. So these redox flow works like this. You have a state and this is a global state. That means that this state is shared by all of your components. Okay? So these UI, which is one of your components, he's going to get the information from that state. So as you can see here in the diagram, it's taking the information from the state. Now, this component or UI or whatever, can dispatch what it's called an action. So you can see now how the action is moving here. So for example, if you are, if you have a button, you can make on the onclick handler to this patch and action. And action is just an object, as you can see here. So as you can see here, these action has a type on a payload, but it can have whatever you want. In redox, the convention is to have a type and a payload. But it can have more things when things get more and more complicated and complex. Okay? So that action goes to the reducer. And the reducer is in-charge of two things. The first thing, which is optional is to process this information. Probably we want, for example, that payload hearing this diagram is 10. Probably we want to multiply it by animal 20. We want to divide it by five. I don't know, make some processing, okay? And after the process is complete, we said that new piece of information to the state. This is how redox works. This is an overview of how redox works. Okay? So as you can see, this is an abstract idea. We can implement these from scratch if you want. But why reinvent the wheel? When we have redex and on top of wheat, on, on top of it, we have redox toolkit. So we have all of these libraries that make all of the heavy lifting for this to work, the idea is very bursty. Okay? So as you saw here, we can implement this promise scratch. And that is not a good idea. So people created redox. And redox makes all of these things easier. However, when you gather experience, work on multiple projects, you're going to see that even redox can be implemented in multiple ways. And those waves can be very, very entangled. Okay? So people said, Hey, there should be a standard way to write a redox. Okay? And that is redox. Redox toolkit is official opinionated batteries included toolset for efficient Redux development. Okay? So basically, this is a standard way of writing Redux. So it provides good defaults for store, set up out of the box and includes the most commonly used redox atoms built-in. So for example, here it doesn't show because this is a very basic diagram, but the state shall be immutable. That means that we shouldn't be able to modify the state in the UI. And for that, we have some atoms here, like I don't recall that the name of this library, but it basically integrates with three dots toolkit. You didn't have to go figure it. You didn't have to know anything about it. You just can't include with redox toolkit and basically makes your state immutable. Okay? It also, as you can see it simple, easy to store, to set up the store, to create reducers. So this thing here, yeah, you have immutable update logic and more. And it's powerful because it takes attrition from libraries like femur. This is the name of the library for immutable update logic and outer dots. And um, animal what, what this orthodox is to be honest, to let your right Mutant Ninja Theory mutable update logic. So we're going to see what that commutative, immutable update logic. It sounds complicated, but it's actually very easy to, once we code and even create entire slices of a state automatically. So this is lysis is a very, very powerful feature of redox token because it lets you create these reducers are very, very easily with these mutated immutable of the logic. And it also creates the actions automatically for you. And yeah, it's pretty, pretty powerful. We didn't have to worry about different kinds of implementations these reducers can have because this can get class. This can be a function, does many things. And we didn't want that ambiguity when writing redox. We want these to be as simple as possible. And we want this to be simple as possible. That's the word. I can find another word for this. It's effective because it lets you focus on the core logic of your app. So you can do more work with less code. So it's pretty, pretty useful. And of course you have here that Get Started button and you can read all of these things and how to install redox little kids. How to configure the store, create an action grids. Last grid Sounds great. Selectors. Oh yeah, that's another thing that I wanted to mention is that we're going to heavily used lectures in this course. And if we were using vanilla redox, we needed to install these reselect library. And this is included with redox toolkit. So we don't have to actually take care of this. We have the create the slicer we're also going to use. And we have more things like these RTKs, currying, which is an optional add-on to solve the use case of data fetching, caching. And I think this is pretty similar to something called React query. So you can take a look at it. There's also think you look for next is about a fetching. Let me see if I can find it here. Yeah. Well, anyways, these optional atom to fetch data. And here you have the land redox part, rid of the essentials tutorial video from the school guys and usage with TypeScript, which is going to be important for us because we're using TypeScript and that makes redox even more powerful. Okay, so I'm just going to give you a quick overview of all of these because there's a lot, a lot of information. I can probably make an entire course only for redox toolkit. And I'm going to keep it as simple as possible. Okay, so I hope you liked this video. See you in the next lecture. Bye bye. 18. Writing DarkMode Slice: Hi and welcome back. So I think the best way to understand redox is to ride redox. So let's create a folder called store. And the store, I'm going to create a new folder called lysis. So we're not going to set up the state right now. Are just going to understand tried to understand redox. Listen. This is licensed that redox Toolkit offers. Well, first of all, I need to still read it right? So npm install. I forgot. Let's go to relax toolkit. Okay, Getting Started. Redox js slash toolkit. So let's go and copy that and install it. Of course, slices, we're going to actually have two slices. The first one is going to be the dark mode is slice, and the second one is going to be the files as lines. So again, I know I might be creating lots of folders. This is a good structure. So dark mode, income upcase. And then this light is going to be with camel case. So it's going to be because we're going to write taps good here. So let's see. First I'm going to import from redox day as toolkit. I'm going to import the create function. And here I'm going to say color. Dark mode is lice. Create a slice. Okay, and we need to pass some parameters here. So let's go to the function definition. And yeah, it expects the state gives reducers and also the name which extends from a string. And so the state is actually the initial state and we want this thing to have. So let's declare a variable called initial state. Initial state like this. And we're going to say false. So the dark mode is going to be false by default. Okay, so we pass the initials date. The second thing that we need to pass is the name of this slice, which is going to be dark mode. You can put whatever you want here. And the other thing are the reducers. Okay? So remember in this diagram, and let's see if I can find a diagram in images. Redox low. Okay, I think it was this one. It was this one again. So we're going to write these reducers here. And remember, these are in charge of two things. Process the actions and also set the newest state. Okay? So the reducers are pure functions. Again. So we're going to say Toggle dark mode. And these are reducer. There are two kinds of reducers. In redox Tokyo. The ones that only receives the state. I'm the one that only receives the well, sorry, the one that received only the states and the other ones received the state and some additional payload. These type of reducers only going to receive the state. And this state is basically what is going to be here. So in the initial state, this can be a Boolean, but remember this can also be an object with lots of properties so that these state here, okay? So now mercy of the state, remember this is the, it can be false or true. So we're just going to return the opposite. So return the opposite of the state. Okay? So when we return something here from this reducer, what we are doing basically is to set that in the estate. And maybe this diagram here is too simplistic because this state is going to actually be the combination of multiple states. And those multiple states are going to be determined by business license. So for example, here we have this initial state from, sorry, this state which had this initial state for the, for the dark mode slides. But remember that we're going to have a, another's lives. Called files. And the files is going to have its own initial state. And the combination of those two states is going to be that global state. So this one here. Okay? So I hope that is clear and if it's dust doesn't it's not there, then feel free to ask questions because I know that if you haven't used a redox in the past, these might be allele difficult. So just to explain it again. Reducer receives a state and optionally a payload. As this is a simple reducer, is just going to return the opposite of the state. And in this case the state is just going to be a Boolean, but it can be as complex as an object. So yeah, this time is just a Boolean. Okay? So after we have created these as lice, we're going to export to things. The first thing is going to be something that we deconstruct for from dark mode, slice that action. So we're going to say Toggle dark mode. And yeah, this is a power of a redux Tokyo. If we were in the US in the reduct, we probably needed to create this action. Okay, and then we'll consumers time and we don't want to write lots of redox codes. We just want to code the logic and that's all. We have, the redox toolkit. We just went when we write the reducers, we write these toggled dark mode reducer. It automatically creates for us this toggle dark mode action. So as you can see, this is action creator without payload. Okay? When we write the files of light are going to see that the type of this action is going to be different. Because for files we're going to write reducers that actually receive a payload. Okay? So now that we have actions, we can dispatch these actions from components. And CBO has that. And when we were going to write something like this and a component dispatch, sorry, dispatch, toggle dark mode. And that's it. You change the state from this slice from true to false or from false to true. And actually don't worry, we're going to write tests so you can understand these before we put this into components. Okay, so that's the first thing. And the second thing that we are going to get from this dark mode slice is the reducer. So if I say dark Moses dies dot read user. This is going to give me that reduces. Okay? And this reducer we need to set up in the store. So the store knows how to handle these action here. Okay? So these dark mode reducer is going to have all of these functions here. So suppose, if we have some other function, some other function like this, state, return tourists and like that, well, It's going to follow the action is going to pass through all of these winds, going to match the name obsolete. And it will know what to do and what reducer to use. Okay, So this is basically a function that is going to be passed a state and an action. And it's going to determine which reduce your hue you shall use in order to modify the state. So again, if you don't understand this right now, don't worry, because we're going to write tests for it. And we're going to also export. Are going to export. Probably like this. This thing here. And that's it. Those are the two things that we are going to export. What actually led me export this default, export default dark book reducer. Like that. It doesn't matter, you can export this without being a default. I'm just going to export this as a default. Okay, So that's it. Now in the next video, we're going to start writing a test for these, for these actions are reducers. And believe me, we in 17 lines we have written reducers, actions and things like that. If you tried to write this in redox, normal redox, although this is a very, very simple a slice, you, you will end up writing lots of code just four days. So that's why I love relaxed. So as I said in the next video, we're going to write a task worthiest. That's going to be our first test. And I hope you liked this video. See you in the next lecture. 19. Tests For DarkMode Slice: Hi and welcome back. Now we're going to write the tests or these dark mode slice, and specifically for the reducers and the actions. So let's create a new file called dark mode, not test dot txt. And here we're going to say import the dark mode reducer from the dark mode. And also we're going to import that toggle dark mode of action. So remember it is a reducer and this is the action. Okay, we're going to write a described block. So basically a described block contains a test suit. So inside of the scratch block are going to write all of our tests dark mode reducer. And we're going to say here, the first step test is going to be unable to enable the dark, moody dark mode if it is unstable. And let's write the implementation of the test. Actually it's pretty simple. We can do it in one line. We can say expect dark mode reducer. And as you can see, the dark mode reducer receives the state of our lines, which is, it can be true or false in this case, it can be a complex subject. For other cases, it can also be on the final, okay? And it also receives an action, okay, So if it is disable, the state should be false, right? I'm, the action is going to be the toggle dark mode, so does the action. So remember these returns a state, a new state. So we're going to say to equal true. If it's false and we dispatch this action with, and we pass this action to the reducer. The reducer, as you can see here, returns the opposite, which is true. And we can do the same thing. But for the other case, it should disable the dark mode if it is enabled. So if the state right now is true, then the remaining, sorry, the resulting states shall be false. Okay, So let's run our tests with MPM tests. Right now it's the only test suite that we have. Both of these tests pass. So I hope you understood what is happening here. So basically, the reducer receives a state and an action and it returns anion state. Okay? So in this case, the state right now is false in this task and the action is the total dark mode action. And when we pass this action to this reducer, resulting state is going to be true. And if the state is true, when we add this action, the resulting state is going to be false. So that's basically it. We didn't have to set up some UI components. We can use Redux like this. Remember if you understand, understand the basics and how it works, then we can test reducers like this. Because reducers at the end of the day, they are pure functions. And right now we have seen a very, very simple reducer which doesn't have any payload. But we're going to see when it accepts the payload and what that means that dv are mutable update logic works. So that's complicated, but we're going to see that it's actually pretty crazy. So hope you liked this video. See you in the next lecture. Bye bye. 20. Configuring The Store: Hi and welcome back. So now we need to start to use our actions so we can dispatch them inside components. So in order to do that, we need to inject the store into our app. Remember, here in theme we have discussed and seen provider where we want to use dark mode from the redox state. Okay? So in order to have access to that type of things, we need to configure redox. And that's the, well, you can say the boring part of this. So let's start by doing that quickly. So inside the store we're going to create an index.js file again. And inside this index.js file we're going to configure store. But for that, for configuring the store, we first need a root reducer. So once again, let's review what a reducer is. So in the slice, you can define reducers. And here these are simply functions, pure functions that modify your state. And they can receive a pay load. But at the end of the day they modified state. So all of these reducers, okay. Are part of these you can say Master reducer. I don't know if that's a term that these dark mode reducer is the actual reducer that contains all of these reducers here. Okay, so that's why in our tests, we passed to these dark mode reducer, the state and the action. And this thing knows what of these functions to use in order to modify the state. Okay, So this thing here we have, actually, I don't remember why I'm exporting. These are the ASA people. Let's do it like this. I think I didn't have a strong reason for doing that, so I'm just going to export this like this. Okay, so let's just make sure this thing pass and B and test. It passes again. So we're exporting these two things here. And this dark mode reducer needs to be inside something called the root reducer. The road reducer is going to have all of these exports like this. We're going to have another slide with an export like this. And it's going to combine them. Okay? So the, so it's going to combine them. So we are going to have all of them in just one place. So inside the store are just going to create the root reducer ab.js file. Okay? And here we're simply going to do the following. We're going to name this combined reducers. And we're going to actually call this compiler disrupt function, which receives an option object. And this object needs to be reducers map object. Okay, So basically what we can do here is to import from license art mode, dark mode. We can import here these dark mode producer. Okay, so here I'm going to say dark mode. It's going to be dark mode reducer. And so this part of the store dark mode is going to have the dark mode reducer, okay, As simple as that. And then we export default, the combined Red Desert. Seeing why this is not getting a sport that I don't know. I guess. So. Now let's declare a variable called store. So we're going to configure the store. So this is a function from red MCAS slash toolkit. And this makes it very, very easy to configure a redox store. So we just pass a reducer which is going to be the yeah, why this is not export? That, That's a good question. Again. Now it's exported. So we're going to import this combined reducers. Combined reducers. Okay? And that's it. We have configured the store. We can also pass another thing called a def tools. So we can use red looks death toll, which is a crumb embrace extension that lets us that bug redox reactions very, very easily. We're going to see that in a moment. So here we're just going to say process of Amdahl's law them is different from production. We didn't want this thing to be run in production, right? Okay, so the last thing we need to do is to export default, historical. And this is how you create the store with Redux toolkit. So it's very, very easy. We combine all of the reducers right now we only have one. We pass that to this reducer option in the configure store method, and that's it. That's everything we need to do. Okay, so now that we have this store in place, we're going to create here a component called redox provider or store provider. Store provider, ok, dot DSX. Going to write the boilerplate code. And here we're going to import from React. We're not going to react. We're going to import props with children. That's our friend. When we want to put these type to the prompt, prompt with children and nothing else. Right now. What else? We're going to need this provider from React redux. And I guess this one we need to install. So let's do npm install React redux. Yeah, I think this is not included with redox toolkit, I guess, because redox toolkit is framework agnostic. So we can use it in other frameworks like Vue.js, Angular. But that's good. So we have the provider. And also, let's see, we need also the store. Obviously, I'm going to import the store from index.js, which is basically this dot here, meaning that we're going to get it from here. Okay? So basically what we need to do here is to do this. And here we're going to add the store. Okay? And is what prompts that children and that's it. That's everything we need to do. So this is a provider, so we need to wrap it basically here in that, that TSX or in index dot js X. I'm just going to put it here in app.js x. So I'm going to say store provider. By the way. And this depends on your application. Some people tend to put it here because then you're, you can make tests for your app. And you can wrap your app in a MAC store provider for testing purposes. So that's basically up to the architecture of your app. Right now we have a very simple app, so we can put it here in the text. But I think it's more comments and put it here. But again, that depends on your application. Okay. So I guess we are right here. Yep, now we have access to the store. So in the next video, what we're going to do is to actually tried to use that in the custom theme provider, like here. Okay, So that's everything for this video. I hope you like it. See you in the next lecture. Bye bye. 21. Typing Redux Hooks: Hi and welcome back. So we have successfully configured the store. Now we need to use the Store. If we go back to our redox flow diagram, this is react, these UI is basically react. So instead react. That means inside any component, we need to be able to do two things. The first one is to dispatch actions, and the second one is to be able to retrieve information from the state. So as we are using React Hooks, there are two hooks that come with React redux that R uses batch and use Electra. With those hooks. We are going to be able to dispatch actions and to get information from the state. But remember, we're also using TypeScript, so that complicates things a little bit. So we need to type these. Dispatch, uses patchwork and use up, you select your hook. So it's not that complicated as well. So I'm going to show you how to do it. And also if you want to do it. If you want to know where these things come from, can go to redox told TypeScript and read through these documentation. And that's basically the same thing that I'm going to do in the video, but I'm going to explain you why we're doing it like this. So let's go and create a new folder called types. And here we're going to put all of our custom types. Okay, so let's go and create the store dot ts. And here we're going to put some texts. Let's see. We're going to first import the store from the store. And I'm going to export type wrote the state. Okay? And first of all, I'm going to get the type of store.gov state. So a start-up get a state is a function that lets you retrieve the state from Redux, okay? Obviously it's not recommended to do it like this inside your components. It's better to use a hook that we're going to see in a moment. But in theory you can do it with a store dot GetState. And then this is a function. So type of gives you the function type, okay? And from that, we want the return type of that function type. Okay? So because when you call this GetState, that's going to return you, as it says here, the current estate tree of your application. So the return type of this function is actually this thing here, the Combined State dark mode Boolean right now. So we want that. And for that, we simply say return type. Okay? And that's it. So if you see now a root estate is empty object intersection with this object here, which is dark mode of type Boolean, which is the type of our, of our state rate right now. So, yeah, it's only that. Now, let's go and create another type called dispatch. And that is only going to be the type of store dot dispatch. So again, store that dispatch is a function that lets you dispatch actions. Let's see, we have the dispatch method of your store and hence by all its middle worse, okay? But we are using react with hooks, so it's better to use the hook and not the thing directly. So up dispatches, you can see it's a very complicated thing. So I'm not going to try to explain well, everything here. Just this is the type of this function. Okay? So now we need to create inside store a hooks dot ts. Okay? And inside here I'm going to import from React redox. Reactions, redox. I'm going to get those hooks that I was talking about, uses patch and use lecturer. So these are the ones that you can use your components. In fact, we don't need to do all of this. It's totally optional, but it's a very good practice to do it like this. And you're going to see why in a moment. And also I'm going to use this type selector, which is a type. Well, it's an interface actually. And I'm going to import from type slash store. We're going to get up dispatch and route a state. Great. So now I'm going to export, const. These new hook, which I'm going to call it, uses dispatch. And it's going to basically be an arrow, an arrow function which executes, that uses patch hook. But I'm going to pass here the app dispatch time. Okay? So now these use ABC dispatch is basically a typed use this patch version of this thing. Okay? So in theory you can use this dispatch. You pass, you pass this type, and you call it. In theory, you can do dialing your component directly. But we don't want to import at dispatch in every component and things like that. So we, we only important use of dispatch and we didn't have to worry about typing things and things like that. So that's why we're doing these kind of things. So the second thing is use absolute lecture, which is going to be of type, type. You select your hook and we pass the rotor state like this. And we say, this is you select crown. So now we have a type selector. And again, we're going to have to do these every time. In our components. We just, we just need to import disease app selector. And now we have a type selector. And the same with u-sub dispatch. We just import US have this patch and we have a type uses Batch. So those little details are because we're using TypeScript basically, if we weren't using TypeScript only JavaScript, now we can use this batch directly and use electro directly in our components. But these are the trade-offs we have with, with TypeScript. And that's basically it. Now we are ready to start using these in our components. So that's what we're going to do next in the next video. I hope you liked this video. See you in the next lecture. Bye bye. 22. Action Creators vs Actions: Hi and welcome back. So I want to make a clarification here because I messed up terminology very bad in the last videos. So when we deconstruct these actions from dark-skinned dark mode slash is lies that actions, what we are deconstructing are actually action creators, not the actions themselves. So what is an action creator? Basically, it's a function that if you call it, that's going to create the actual action. So remember an action, if you go to a redox flow, it's C, it's simply this object here, type that has a type and a payload. Okay, so that's the convention, can have more things, but the convention is to only have a type and a payload. More complex application, of course, you're going to see more things in that object. So to create that object, we simply need to do something like toggle dark mode. And if I do that, in fact, you can see here that this is going to return an object with a payload on the fine because this is an action career without payload. Another type of a string, the type string is going to be the name of the action. And redox toolkit is going to take care of that, is going to take care of naming that action for us. Obviously, you can change that, but we're not going to do that here. So in the task, remember that we pass the action creator, but we need to actually pass the action. So if I do this, the test is going to still pass. Okay? And if I remove the parentheses, it's also going to pass. So my guess here is that somehow these dark mode reducer is taking this action creator calling it, and that's how it's able to modify the state. But this is more technically correct, passing the action object itself. So taking advantage of these explanations to fix this test as well. So I hope you understood this part. And if you didn't, well, don't worry, just ask the question and I'll be happy to answer it. Okay. So I hope you like this video. See you in the next one. Bye bye. 23. Implementing Dark Mode: Okay, So I think we have gone through the very difficult part of redox. So now let's start our state. So once again, if you don't remember, Let's look at this diagram. We need to do two things, is patchy and actions and receiving information from the state. And for that we're going to use the hooks, the tight hopes that we create it. So let's say this is up dispatch and use absolute lecture. Okay? Um, so first of all, I'm going to change that in the custom theme provider. So remember here, basically hardcoding dark mode false, but now we have a state where we can get this information. So that's where we're going to get now that information. So let's get 0s. Okay? And the first thing that we're going to get is the state. Okay? So let's get the States. And then we need to get from state. We need to get the dark mode. And that's it. That's how we get the dark mode from the state. As easy as that. Okay, So the second thing is, well, we need to set these somewhere, right? So let's go to components, common header. And we're going to create a new component. And we're going to call dark mode sage, dark mode, switch that TSX. Let's use our a snippet. And well basically, if you go here, well not here. Well, let's search for switch component. And also let's go to Redux toolkit. And yeah, I wanted to do something similar to this. Not exactly this, but something like this. Okay, so we're going to use the switch components from material UI. And we're going to put a Layer icon here. Okay, so that's very easy. And yeah, let me just check if we installed material UI icons. So yeah, we haven't installed that yet. So in order to use icons, we need to install another tendency. And that is going to be mature UI. I can dash material. So let's wait for this to finish. And in the meantime, let's go to our new components in here we're going to make a React fragment. So something like this. And I'm going to use that switch from material UI. Okay? So from that switch, that switch, we need to pass three, actually three variables. The first one is the color, which is just okay, so that's the color of the switch. And then we need the onchange handler and the checked attribute. So it's checked, it's going to be in one side. And if it's unchecked, it's going to be another side. And the onchange handler, we need to dispatch an action. Okay, So let's do exactly that. First of all, let's get dark mode. Let's get it from US. App selector. And again, we need to state the first arguments. They dark mode the second argument. So now these dark road is a Boolean, so we can simply say check is going to equal two dark mode. In fact, we can make these more explicitly to say is start mode enabled? Okay? And now we have that Boolean. And now we're going to get the Dispatch, Dispatch her actions. So it's actually like this. We're going to get used up Dispatch, okay? Our going to create that on change, dark mode or whatever. Okay? And is going to be a narrow function. And we're going to dispatch. And we're going to get that toggle dark mode from a store. There's lashes licenses, lashed dark, light, dark mode. And remember this is the action crater, so we need to call this, and this will give us the action, the actual object, and we simply dispatch that action. So if we go to our redox flow, this is the event handler. In our case, we're using the onchange event handler. And inside these onchange event handler, we are dispatching an action to our store. And redox toolkit mates makes all of the heavy lift to match that action to a reducer, to the corresponding reducer. And the reducers going to set the new state. And the new state is going to be reflected in the UI. So the new state actually is going to be reflected in the custom theme provider. And also here in these check on this dark mode switch components. So this is dark mode enables going to chain from true to false or false Situ. And this component is going to re-render and the checked attribute is going to pass from true to false or four, or four. And the corresponding UI changes are going to be scene. Okay, so that's the only thing we need to do. We're going to say onchange is going to be on change dark mode. And that's it. Now we have a dark mode switch. Of course, we need to include it here, and I'm going to put it right here, dark mode. Okay, so now we are ready to go. So let's see npm start. Okay? Let's wait for this thing to start. Yep. So let's go here. Yeah, we have now this switch here. Now let's put that icon that I, that I missed. So where is it? Yeah, we have two from we have to import dark mode icon from material you slash icons, material slash. The name of this icon is brightness to you can, you can search by Julie UI icons. Here we'll just search material icons. And here you can search for that if you type brightness to, or you can see that this is the icon we want. You can use brightness three if you want. That's up to you. Okay? And we simply are going to say dark mode icon, an octet. Let's see the changes here. And now we have that little icon there. Okay, so if I do this, you can see it's pretty, pretty cool. So the other thing that I wanted to talk about, redox deafness. So if you search for redox DevTools, this is actually an extension for chromium browser. So you can visit embrace. You can. Is it in Google Chrome? I'm not sure if you can see it in operand and Microsoft Edge. But yeah, you can, you can install this redox dev tools now. And if you open the DevTools, the Chrome DevTools, here you're going to see that we have this redox. And this is very, very useful. So this init, if you go here and you go to the state, you're going to see the estate asset screen. You can see this chart to the state, has children count of one is dark mode is right now false. Or you can see like a JSON object, or you can say like this. And then if I dispatch in action, you can see that I can see this action. I can go to the Action tab. And as you can see, it has a type which is dark mode slash toggle dark mode. So this is what I was telling you that Relax tool kit sets the name of this action for you. And the type is going to be the name of the action. And this is set up for you automatically. So that's based on the slice name and on the reducer method name. So that's pretty, pretty convenient, right? If you weren't using redox toolkit, you have to this type manually set the name of the action memory and all those things. So this is a pretty awesome. Also, if you see this div here, then you're going to see that dark mode went from false to true. And you can see that dark mode in the state is now true. And will I haven't used these two tabs too much. So yeah, I cannot tell you too much about them. But this is the basic functionality of these redox dev tools. Okay, so now let's try to refresh this page and see what happens. Oh no, our dark mode disappeared. Why is that? Well, the reason is pretty straightforward. We aren't persisting our redox state anywhere. So if I refresh this, just going to disappear because the initial state of these remember, is false. So the next question that arises is, how do we persist the state? And that's a question that we're going to answer later. So I hope you liked this video. See you in the next lecture. Bye bye. 24. Configuring Persistence: Hi and welcome back. So we have successfully created these darker mode switch for our app. If we refresh, we are going to see that we're going to lose actually that a state from redox. Okay? So how do we fix this? Well, it turns out there is npm package called redox processes. And this is basically package that lets you persist and rehydrate that Redux store. We can use multiple storage engines like local storage, session storage, sync stretch. We're using React Native, local for it, which is something more sophisticated. That uses an API very seemingly, very similar to local storage, but it uses Web SQL behind the scenes, I think. So let's go here. Yeah, local forage is a fast and SQL storage library for JavaScript. Improves the offline experience of your Web App Bot using a synchronous storage index DB or Web SQL with a simple look at local storage like API. So it's like local storage, but more sophisticated them. Recommend that for web. In this course, we're not going to complicate our lives. We're just going to use local storage. Okay? So yeah, that's basically it. It has lots of configuration. Here. You have a QuickStart of how to use it if you want to configure these from scratch by using the grid store for redox. But remember that we are using a redox toolkit. So we are going to see how to use it with redox toolkit. So let's go at the usage guide of redox toolkit. And in this section, use with redox persists. It says if using Redux versus usual specifically ignore all the action types it dispatches. So those action types are these flush rehydrate boss persists, birch and register. Okay, so why we need to ignore these things? Well, redox toolkit, as I said, is pretty, pretty awesome and it implements best practices for us. So it contains by default is serializability middleware. And these short-term Doesn't that the dispatch actions that are not serializable. So for example, let's read throughout this accustom middleware that any non serializable violence happening included in the state or dispatch actions modeled, redux immutable, steep, invariant, any detected non serializable plans will be locked to the constant. Okay? So this middleware is added to the store by default, by configures during get default middleware. And you can customize the behavior of this middleware by passing any of the supported options as a serializable check value for get default middleware. So basically here it gives you an example how we can ignore those actions. So it's a best practice not to non serializable things in the state. I have seen in the past how people react components and very, very weird thanks to the state. And although there is no one's stopping you from doing that, It's not a best practice. And that's why relaxed Circuit says, Hey, we're not going to stop you doing that. Because this realizability middleware, I think it's only available in development mode. But we're including these. And seeing you in the console, Hey, you're doing with stuff. So stop doing that leaves again. So this is basically the configuration that we want to reproduce in our project. As you can see, this is the most important part. Ignore actions to ignore the sections that are non serializable. So sadly, if we want redox toolkit to work with real expertise nor those actions. And this is a perceived conflict. The key is the root, the root stage, because we can also make persistence on sub-states. So that's more sophisticated, but redox persists is very, very flexible. This version, I'm actually not sure. I think it's for migrations. But as I said, I'm not actually sure. And the storage well, we saw here in that documentation that we have different STR attendance and storage corresponds to local storage. And if you want to use a storage session, then use this. And we want to use anything else. There are lots of these. Then you can use them. Okay, that said we need to create the persistent reducer, pass it to the configure star function, and then create the persister and add these persist gate. And we have these loading option, which is optional. So this is for when you're going to see it better with a radix DevTools. But if for some reason it takes sometimes to get the data from the disk, then we're going to want loading component to show. So it shows some loading state. Again, I recommend highly to read this documentation. For example, here it shows you nest the persists. Basically you can do the root persist config. And if you have a sub-state leg up, then you can do go figure a configuration on that. So the key will be off. And again, you can blacklist. You can whitelist states that the slices of the state black list and white list here. What else? You can also have this estate reconcile, which basically you have three options, hard set, automatic, level 1, level 2. Again, I recommend you to to read throughout this because it's bringing interesting. For example, if you have two common state and initial state is this, then the reconsolidate is going to be this. You can have other options like this or this one. And also you have here in the API, the purses reducer for example, which is basically this thing here, is going to return and has reducer and it's a concrete object with our required compute the key and the storage and other conflict, the white is black, leaves the version. The state reconsider and that debug. And persist doors basically retronasal are persister object. And that persister object is very, very interesting because you can, for example, call these things Birch flush button persist. I haven't had a project where I needed to use his persistence object and manually. But I guess, well, you have apps that are very, very complex and maybe, yeah, you need to do this manually. Right now I can think of a good example, but you know that you can call these methods here. And if you call these methods, for example, perch, then you're going to basically dispatch this action here, this bird's eye view call persist. You're going to call this thing here. You're going to dispatch the fact in urine. Recall again, these you call flight, you're going to stretch this thing. We had what's going to be called. When you refresh the page, For example, we are going to see that indirects DevTools. Okay, So I think I have talked a lot here. So let's actually do that configuration sprays symbol. Well, first of all, we have to install redox persist. And we actually don't have to install any types because if we go to the top of this page, it says that this package contains built-in TypeScript declarations. So that means this TypeScript friendly. Okay, so now that we have this package installed, let's go to the store and let's go to the root reducer and who are going to create our persist, persist config is going to be, and it gives going to be the root states. So remember, the red state contains the dark mode, which is of type Boolean. We need the storage. So we're going to actually, from redox persists, We're going to get persist reducer. And the storage satellites and other parks. And storage is great expertise. Lashley is less storage like this. So we're going to pass these storage. We're going to pass though. Nothing else actually. So now we're going to create these persistent reducer. And this is going to be basically perceives reducer has a perceived conflict and the combined reducers bind with the reducers and we export default, this thing here, and an index with change name to persist that reducer. Okay? And what else do we need to do? We need to remember, ignore those special actions. So we need to import from redox persist, we need to import what are they? Flush. Its pos persists, birth register and rehydrate. Okay? And I think I also need persistent store from here, persistent store. So here what I'm going to do is say me though we're going to get that default middleware, get default middleware. Okay? And basically I'm just going to call this thing with 0 lies a little tag. And the NOR actions are going to be all of those. Flush, persist, Birch, register and rehydrate. Okay, cool. And the last thing we need to do is to export from here the persister object, which we get from the store. Okay? And in the store provider, we need to do a last thing, which is basically get dispersed. And gate from redox first sees this slash integrations that slash react. Okay. Let's close this thing here. Okay? And this is failing because we need the persister which we've already created. We imported from from dot, which means index.js. And again, here we can pass a loading component, which it's going to be our loading component that we created in the past. Okay, so let's make sure this goes like this. Okay? So let's go to our application. Go to react up here. So you already saw that the state is persistent. So let's see here, let's go to state. As you can say, the initial state is false for dark mode, then redex, persist, throws or dispatches dissection, which we, it's not modifying the dark mode. And then it dispatches rehydrate, which basically changes the dark mode to true. Okay. And these rehydrated to draw. Okay? So, yeah, this is what sees does behind the scenes sprinkle and now we have a persistence here. Interrupt. If I turn this off, you can see it's maintained. So yeah, this is working perfectly. So as you can see, it's very easy to add persistence to our app and relax, persist faculty. Very, very flexible. So I hope you liked this video and see you in the next one. Bye bye. 25. Creating Files Slice: Hi and welcome back. So we have configured persistence. Now, let's deep dive into what I consider the, probably the most complex part of the course, which is managing files with the redox. Okay? So basically we are going to create another folder inside his life called files. Okay? And what we are going to do here is to create a new file called file.txt. Nothing too special. Okay? And well, let's import from redox toolkit. The creators lives. Okay. And for now, let's create the file, the lies like this. Files as lines is going to be equal to create a slice. Okay? And obviously, we need to pass lots of configuration here. So first of all, we need to actually declare an interface or a type for the files state. Okay, so what is going to be that files a state. So let's say Export. Let's say this is going to be an interface files. It can be a type as well. It doesn't matter really. In fact, if you didn't know there's like a like a proposal to keep one of those type or interface. I don't know if the maintainers of TypeScript have considered that yet, but just say, you know, type an interface probably in the future are going to be the same thing. So they're going to be replaced with one or the other. Okay, So these files state is going to consist three things. The first one is going to be user files, and this is going to be a special or a custom type. And actually that custom type, we're going, we're going to declare it here in types. So I'm going to create a new file called user or maybe files. Okay? And here I'm going to export an interface or type called user file. And this user funds going to have five things and I'm going to explain them. Each of these things. So first of all, a string. I don't think this needs too much explanation. This is just the ID that is going to identify the file that we import. Then the name, which is going to be the name of the file, relative path. So relative path is going to be something like this. For example, if I click here, copy relative path. So it's going to be something like the source slash slash file.txt. Ok? And it's going to also have the code, which is going to be strings. So the code is the code itself and the extension, which is also going to be a string. So as you can infer from the relative path, we're going to be able to get the name and the extension. So it's going to be handy, very handy. We have these two pieces of information separated from the relative path. Okay? So I'm going to use these type here. And I'm going to say that the user files is going to be an array of user file. So for that, I simply import from this type slash files file. And I say user files is going to be used for file. And these brackets here, so these denotes that this is an array of user files. Okay? So that's the first piece of information that we're going to having these file sustain. The second thing is going to be active files ID's. And this is going to be an array of strings. So as the name indicates, we're going to have active files in our editors. So for example, here I have two active files. Files are ts and files, and files that he has been capitalized. So these two files, obviously the IDs and the active files ID's is going to be an array contains those IDs. Okay? And last, but not least, we're going to have the editor active file ID. Okay? And this is going to be a string, or it can be known. Okay, So basically this is going to be the ID of the file that we are currently in these examples, it will be this file has the Ts. The idea of these files going to be the editor active file. And a quick note here. We can also do it like this. Okay. And probably that's more correct. But I have experienced that sometimes these cans with some difficulties regarding typing and things like that. So I'm going to stick with a string or null. Okay? But if you have like more properties like Prob 1, 2, 3, 4, and all of these are optional, then yeah, it's probably better to do it like this. And obviously specify the type. So like this, like this, like this. Okay? But here it's not a big deal because we are only going to have these three things here. Okay? So now that we have these files, a state type are going to declare also the initial state, okay? And I'm also going to export the initial state because it's going to be useful for the tests. And note that in the dark mode slice, I didn't export it because it was just a Boolean. But here it's going to be handy if we exported. So this initial state is going to have the file, a state or files as date type. And well, the initial state is going to be user files, an empty array, active files ideas again, an empty array and editor active file ID, which is going to be null. Okay? So this is going to be an initial state. Now, we can basically here configure our slice by saying name. Well, it's going to be files, initial state, and our reducers. Okay? So right now I'm going to put an empty object here, but actually we're going to have five reducers this time. So it's not going to SBC as the dark mode slice. Okay? So also we can export const, the piles reducer. Just going to be file slides that producer. Okay? And remember we need to include that in the root reducer. Here we have all of the reducers combined. So I'm just going to say here files, and that's going to be the files reducer. And let's move this here and here. Okay, so that's it. That's everything we need to do for now. In the next video, we are going to code this reducers and also test them. Hope you liked this video. See you in the next one. Bye bye. 26. Creating Files Reducers Logic: Hi and welcome back. So now it's time to write the logic for direct users. So let's start doing that. The first reducer is going to be called set files. And this time it's going to receive the state and an action. So this time we're going to receive an action. And obviously this action needs to be tight because we're using TypeScript. And this is going to be of type payload action. So that's an import from redox jazz lashed Toolkit. So you can import it from there. And these receives the type of the payload in these brackets. And that is going to be the type you sir file array. So just as this one here. So now what are we going to do? We're going to say a state user files is going to be equal to action debate. Okay? So basically we're setting user files to be whatever the payload of these actions. And that is these mutatis immutable update logic. Okay? Why? Well, let me explain. The state is supposed to be immutable, so you shall not in normal redox, update the state like this. You should first make a clone of the state, okay, by using whatever tool you want, make a deep clone of the state and then make the changes in that clone, the state that the redox toolkit, as I said, is pretty, pretty awesome and you can do it like this. And although it appears that we are maintaining the state directly, we're actually not doing that because with these immer and Orthodox, that lets us write mutable or immutable of the logic like this. So, yeah, it's a complicated term, but it's actually just this. Okay? So also what another thing that I'm going to do is to set the active files ID's to be an empty array. Okay? Because the set of files is going to be called when we upload a directory. And well, of course, we're going to take take care of that later. So that's our first reducer. Our second reducer is going to be an active file reducer. Again, this is going to take the state and an action which is be a payload action. And the type of the palate is going to be string. Okay? So basically this is easier. We were going to say state active files ID's, and we're going to push action that payload, which is going to be the ID of the new active file. So a simple as that. Then we are going to say remove active file. Remove fact is active. Yeah, remove active file. And here I'm going to get an action which again is going to be a payload action. The payload type is going to be string. This is also easy. We're going to say a state dot active files like this is going to be equal to state dot active files. I did dot filter. And we're going to say, well, we're going to get the file ID, okay? And we're going to filter all those files. Were the file ID is defined from the actual payload, which remember, is going to be the ID of the file that we want to remove from the redox state. Okay, now let's go and write this set editor active file. Again, this is going to get a state and action, which is going to be a payload action. And the type of the payload can be string or it can be null. Okay? And we're going to say a state dot editor at defiles going to be action that payload, as simple as that. And we have four, we need one more. And that is going to be more complicated. We're going to say Update file code. And we're going to get that the state and the action is going to be payload action. And the type of the payload is going to be a little more complicated this time. It's going to be the file ID that we want to modify and the new code, which is also going to be a string. Okay? So here we're just going to say, we're going to deconstruct from action that payload. We're going to deconstruct the file ID. And also the new code, which is going to be string. Okay? Then from the state, I'm going to deconstruct the user files. You serve files. And I'm going to declare a variable called user file update. And that is going to be found by iterating through this user files. Finding the file like this, or file ID's equal to violate. Okay? So basically we're iterating through all of the files in the state and finding the one with the file ID that comes from the action payload. So nothing too complicated there. And we're going to say if the user file, user files of debt is found, okay, because remember, find can return and also undefined if nothing is found. So if this is defined, we're going to simply say user file dot code is equal to new code. And that's it. That's everything we need in order for making our code editor to work correctly. So nothing too complicated. Believe me, if you were writing normal redox, you'd have to do first the clone of the state and think like that with redox toolkit is much, much easier. So now that we have these reducer, remember that they create action creators. So what we're going to do is export const, all of those actions creator. So from files like that, actually, I'm going to get, I'm going to get set files. I'm going to get active file, remove active file, update file code, and set editor active file. So remember, these things here are actually graders. So if I hover over these, one of these, for example, it says action creator with payload. And the first argument is going to be the type of the, of the payload. And the second one is going to be, I guess the type, the type of the type. So remember, an action has a type payload. So the second argument I guess is always going to be the type of the type. So yeah, that's it. And well, in the next video, we're going to test all of these reducers. Remember, reducers, make sure to put as much as possible of the logic of the business logic in the reducers. And that's it. I hope you liked this video. See you in the next lecture. Bye bye. 27. Adding Tests For Files Reducers Part 1: Hi and welcome back. So let us start writing tests for these reducers. So let's start by creating a new file called file test.txt. And here I'm just going to import from files, a lot of things actually. So active file, well, first, initial state to be consistent. Then the action creators are active files. Remove active file, editor, active files and files, and update file code. So I'm going to import all of those things. I'm going to create the describe log files slice. And the first test is going to be either return the sorry, it should set user files when the action is set file. Again. So the theme, okay? So the user files is going to be an array. Remember? And that array is going to have an idea of what it can be, whatever. It's going to have a name, we're going to name, the name is going to be index.js. It's going to have a relative. So for example, source slash index.js. And the code obviously is also going to be the string hello console log, HelloWorld or something like that. Okay? And the extension of these files. But let's put the number 1 with an ID of name. I know server.js or stuff like that. Source, server.js. Hello world, hello server or whatever. Just fake data. And then I'm going to construct the expected state. And expected state is going to be, well, first of all, I'm going to get the initial state here. And I'm going to say, well, the user files is going to be the subject here. And also I'm going to say that the active file size is going to be an empty array. So this is going to be the expected the state after, after we pass the set files action to the files reducer. So we're going to say expect files reducer, which by the way, we should also get from here from these import. Okay? And remember these files reducer gets the first argument's going to be the state, and the second argument is going to be the actual game. So we're going to say set files, which is the action creator. And remember if we call it, we're going to actually create the action and the payload needs to be the user files, okay? And sorry, this will be initial state. Okay? So this returns the new state. So we're going to say that this is going to equal the expected state. Okay? So let's see what happens if we run npm test. Let's see if our test passes. And yeah, our test is passing. So let's write more tests. So the second test is going to say it. And a new violated. When the action is adducted file case it will add a new file I did to that array. So the final indeed can be whatever. I'm going to say. I'm going to create the Expect to the state. Okay? So the expected state, again, I'm going to get first, we're going to do to get the initial state. And then I'm going to say active files id. And this is going to be an array. And here I'm just going to put this ID one. And then I'm going to say Expat Files producer. Passing initial state. We pass the file and we call it with these ID of one. Okay? And this must equal the expected state. So let's say if our test is passing And now we have two tests that are passing. So this is a pretty cool pattern for reducers. We build the expected state. Then we, we pass the action with the corresponding payload and make sure that this new state is equal to the expected state. Okay, So let's start adding more and more tests. So the other test is going to be it shold removed a violent when the action is removed, active file. So let's see what we can do here. So I'm going to build something called a modified initial state. Modified initial state, which is going to be the initial state. But right now it's going to have an active file ID and fill. And I'm just going to put one here. And the expected state, expected state. And it's to be again the initial state Or rather than modifier initial state. And the IP file. The files id, is going to be an empty array because we're going to pass in the payload of the Remove active file. We're going to say we want to remove the file with the ID of one. Okay, So that's what we're going to do right now. Expect files reducer. We pass the modified initial state. We call the remove active file with these, one has a payload and this should equal the expected state. Okay? So let's say we have three tests that are passing. Now, let's add a test for for the, for setting the editor active file. So it should set the editors active file when action and the action is set editor active file. So here I'm going to say expected state. Again. We get the initial state and we get the editor, active file, editor, active ID to be one. Okay? And then we simply say X files reducer. You pass in initial state, we pass the set editor active file. And here I'm just going to say one. Okay? And this needs to equal the expected state. Okay? So let's say we have four tests are passing. Now let's make the same test. But remember, the editor IP follows D can be. She'll set the editor at the file ID, that ID to be No. Okay, so this is going to be no. And this is going to be no. Okay, So it's passing again. So we have five tests and we still need to make tasks for this update file code. We're going to do that in the next video as these ones getting a little too long. So I hope you like it. See you in the next video. Bye-bye. 28. Adding Tests For Files Reducers Part 2: Okay, Let's continue completing the test for this. So we need to add a test for the op file. So we're going to say it should update the code of a file. When the action is update Falco code. We're going to first make the payload of the action which is going to be violate the equal to one, whatever you want. And the new code is going to be something like console log change or something like that. Now, we're going to create the modified initial state to have initial state. Okay? And the user files, that's going to be just one file with an ID of one of the code can be whatever console log will work. The name can be index.js. The relative path can be source, index.js. And extension obviously is going to be okay. And now expected the state, the state is going to be modified state. And then the user files. It's going to be the same thing. But, sorry, the same thing. But this console log that helloworld going to be hi, this console log change. So like this. And now we need the expect statement Alice Leanne. So expect Biles reducer, modified initial state. We pass the update file code with a payload. And this is going to equal the expected state. So let's say that this test is passing yards passing. Okay? So remember here we have an if statement, so we also want to cover that IF statements. So let's make one more test here. We're going to say it's shown not update the state when when the file is not found. Okay, so actually let me copy and paste most of this thing here, like this. And here in the file ID, or going to say that the file ID right now is going to be two. So now the test is failing because these expected state is not correct. The expected state in this case shall be modified initial state. And if we do that, now the test is passing because the expected state didn't change. Okay, so that's it for this video, I think now we have a good test suite for this thing here. So I hope you like it and see you in the next lecture. Bye bye. 29. Adding SelectActiveFiles Selector: Hi and welcome back. So now we're going to create our first selectors. So what is a selector? Well, as the name suggests, it is a way to select something and that something is information from the state. So if we are in a very like simple app, we can select things from the state. Like here, like what does your customer and provider. We just get the state and the dark mode. So that's completely valid. Very simple. But sometimes we want to make processing from the information that we get from the state. And that's where selectors are very handy. So let's create a new folder called selectors. And let's create a folder here called select the files. And here we're going to create the slag, the files that ts, and also select Active Files that test. But this time, I don't want to complicate my life too much. That's why I'm going to make this test B dot ds. This is completely valid because remember hearing in ts config, we have these allowed jazz, true. And these basically says that a lot of JavaScript files to be a part of your program. So we can write, we can make JavaScript TypeScript. And actually these is a recommended in some cases. Like when, for example, you don't want to complicate yourself too much with typing tests because it makes your tests a little bit on readable, just because you want to satisfy tasks TypeScript. So I've seen this pattern a lot. Actually. One of the components. I'm also going to write it as DSX and not TSX because there's lots of unnecessary things we need to do that are not related to the course. Just to, just to satisfy TypeScript. And I don't want to make the course too complex and explain things that are not related to logic and things like that. So, yeah, that's the reason I'm going to use JS for this because I don't want to spend so much time satisfying TypeScript. Okay, so here I'm going to import the select files, which is going to be a selector. Right now it doesn't. There's nothing here written code. So that's why we're going to follow the test-driven development approach. First, we're going to write the tests and then we're going to make everything to make the test pass. Okay? So the tests are going to write one test and it's going to be ensure return only the active files. Okay? So remember that if we go to our slices and we go to that files, a state interface, remember that the active files ID's just as an array of strings. So those strings are going to be the ID of the files. But we want to get not only the IDs, but also the information of the file itself. So we call have done something like this in the first place. But we want the best practice to keep as little information as possible in the redox state again. So here we will have more information that's needed. So we can simply do something like this. And just to strain the IDs will, will make the redox state more. I mean smaller. Okay, so let's start by creating some user files. Let's create three user, three user files. Because the first is ninth year one and index 1, the relative source, index one that the code can be whatever console log Hello World in the extension can be js. Okay, let's copy this three times. Changing the idea. Probably this number as well. The code can stay the same. Okay, so now we have user files. And I'm going to also say. That the active files ID's are going to be 31. And this is going to be right now files, user files, and the active files ID's. Okay. So this is why I don't want to use TypeScript for this test because otherwise I will have to also include things like the editor active file ID. And although I can do something like this at 35, no. Okay. And also I have to set the dark mode and things like that. And I don't want to spend so much time feeling things that are not necessary for this test. So that's why I'm using JavaScript in this case. So I want the expected results to be, obviously, we need this file here, so I'm just going to copy this file here. And we want the first file. Okay, so that's basically what we want these selector to return. So I'm going to make the expected statements saying select active files, a state to equal expected results. Okay? So now obviously this test is not going to pass the firewall, can test. The test is failing. I was that's expected. Have any code here. So it's time to start coding these functions here. And we're going to see very interesting things. So for these, we're using TypeScript. And before doing that, I wanted to show you that redox toolkit. Redox two kids selectors. We are already have a function to create selectors with redox toolkit. And it says here that creates electric utility from the re-select library. Re-export that for ease of use. Okay, So this is a completely separate a library, but redox toolkit ships with this library. And as you can see here in the ReadMe, this is simple molecular library for redox inspired by, well these things here. Yeah, so basically three things. The selectors can compute the rash data, allowing redox is toward the minimal possible. And so that's what I was saying. Selectors are efficient as electors, none recomputed own as one of its argument changes. So basically only if the one of the files changes. I mean, if we and that's only going to happen if we upload a new set of files, then that's the only time that this selector is going to be recomputed. Otherwise it's going to have an internal cache or something like that that is going to return us the same result. Every time selectors are composable, they can be used as input to other selectors and you can read more about it. So this is not specific to relax toolkit. This is completely separate library for re-accelerate of circuit. And it's pretty interesting. You can use it. You can use it even without redox, but obviously that wouldn't make much sense. Okay, so let's start by coding this thing here. So first of all, I'm going to create these select Active Files. This is going to be only an arrow function. Okay? And from these arrow function, I can export default that creates selector. And this comes from reselect. And these is going to receive the state, which remember if it's of type route the state. So that's interesting because now we can get from here a state that files, okay? And basically this statement files is the first type argument. The information that is going to be passed to these select active files. So here we can say files. And the type of this thing is going to be files and state. Okay? So that's why I exported this type from the files dot txt file. Okay? So the second argument is going to be that function select Active Files. Okay? So now we need to write all of the logic here, and it's actually very, very simple. So let's get from files. Here. We're going to get the user files. And the active files ID's. Okay. So first of all, I'm going to create a user files map. First let me create the type of user files map. So basically this is going to be an object where the keys going to be whatever string and the value is going to be a user file. So let me explain you briefly. What is this? Suppose that the user files is something like this. So ID1, code, whatever. Okay? Suppose we have ID to go, hello world whatever. Okay? And obviously this has more, more information. They use our files. Mab is going to be simply something like this one. And then id1 code, whatever. And to ID to code Helloworld. Okay? So we have passed from an array to an object. Okay? So now we can access these IDs in constant time. We can make sure that sum, for example, we can say, we can assert that one is in this object, in these user paths map in constant time. With an array. We cannot do that because we will have to iterate through the whole array and find the ID1 is in that array. So that's going to make our select Active Files more performance. Okay, so let's start doing that. That's pretty easy to do. We simply need to declare this const, user files map again. And I'm going to say user files dot reduce. This accepts the previous value and the current value. The previous value is going to be the result. And the current value is going to be the active file. Okay? So the first argument reduces a callback and the second argument is a initial value. It is going to be an entering. And here that is going to complain and say that this is of type user files map. So to make TypeScript happy, we are going to say that this array, sorry, this object is a user files map. And then here I'm just going to see a result of active file dot ID is going to be equal to active file and return results. So that's basically it. Now we have a user files map where each key is the ID of the file and the value is the file, the user file. So now we can do the following. We can return active files. Id's, that map. And we're going to get the Actifed. And we simply say user files, map, active file. And that's it. If we run the tests that yeah, now the test is passing. Okay, um, so a quick note here. This process here is also called redox world. Well, in software development in general as normalization. Okay? So if we go here and see here these normalizing state shape, this is primary, that's dot js.org, not from relax socket. So this is an article that I suggest to read. Let's see what we have here. So we have these blog posts that is basically an array of objects. And these array, and each of these entry can comments and his comments is again an array of objects. Okay? So here, this structure is not so scalable when you have very, very complex apps. What is the reason behind that? Well, here, the reason is explained. So when a piece of data is replicated in several pieces, it becomes harder to make sure that it is updated appropriately. Nested data means that the corresponding reducer logic has to be more nested and therefore more complex. That's true. In particular, trying to update a deeply nested field can became, become very, very fast. So, yeah, I can see that happening. When you have, for example, you want to modify this comment. You have to go to pause than searching comments and then search for the idea of the carbon. So yeah, it can go very, it can become very, very fast. But the most solid reason for not doing this is this one. Since immutable data update require all ancestors in the state tree to be copied and updated as well. And new object reference will cost connected UI components. So re-render and update to a deeply nested that object force. Totally unrelated UI components to rerender in if the data there, this plane hasn't actually changed. So I know there's a lot of texts, but let's understand what that means. So remember that until you that if you were using normal redox, you have to copy the state before modifying it. Because a state shall be immutable and relaxed. Meditative, immutable update logic thing. Okay, But with normal rate, that's not the case. And also behind the scenes, with that emerge library, a redox delicate, it's doing the same. So if you're, for example, updating very nested things, you will also update this part here. So the ID and author body and so on. So that will cause I re-render even if you are not changing anything of this thing here. Okay? So that, that is actually not good. So the solution for this is to normalize the state. So there's no, Well, I don't know if there's a library out there for doing that, but this is something that you have to, do. You have to architect, okay? And that you have to decide by yourself how to do it. And here's the basic concepts of normalizing data. You can read through all of this, but basically it's doing this. You have the posts. In our case it will be Files. And then you have these by ID. And this is going to be an object where basically the ID of the key of each, of each entry of this object is going to be at the idea of the entry, and then devalues going to be the entry itself. So in our case, if we want to normalize, it will be the ID of the file and then the file itself. Okay. So yeah, this is, these will prevent us or if we, if we did that, then we wouldn't have to do this again. But actually, these will be an overkill in our app ID. So that's why I didn't want to do this. And I didn't want to complicate things from the beginning. So if you want, after we finish this course, you can try and as an exercise, try to normalize the state. And the only thing you will gain, you will gain by doing that is that we wouldn't have to do this user files map, I guess. And also we don't have many nested data. Remember that you serve file has been to be a user Paolo array and we're going to have nested data there. But basically that's normalizing the state here. You can see that the comments again is by ID. And you can have all this, all IDs which is useful for ordering data and things like that. And again, the same with users. And I recommend to you to read this article not that long. And it's going to teach you how to normalize the state. I have to warn you, this is sometimes a very difficult process, especially when you already have an app up and running and then you join a new company and you say, Hey, I want to normalize the stage had probably, they're going to tell you, well, the app is running without that change, so let's keep it like that. That's the most probable, probable thing that you will hear as an answer. Because life ain't easy and making this change in large cap that doesn't have these patterns. Probably not a good idea unless you know what you're doing. Right. So yeah, that's something I wanted to talk about, you know. So so that you're aware of it. And yeah, that's it. I know this video was too long, but I hope you learned something new here. I hope you liked this video. See you in the next one. Bye bye. 30. Adding ReadFile Function: Hi and welcome back. Now it's time to start dealing with more complicated stuff like thunks, raining files, et cetera, et cetera. So first of all, let me create a new folder called Utils. And here we're going to create a new utility function, which is going to be for reading files. So I'm going to name it read file dot js. And here we're going to explore these read file function, which is going to receive a file. Okay? And first of all, let me explain why I don't want to make these TypeScript file, but rather a JavaScript file manage because the type of the file, which is not that easy to understand. Ron, many students in the last version of this course were very confused about this. I have decided to drop it. Because again, it's just a matter of satisfying touch grid and it adds more complexity to our app. If you can or if you want, you can search for the type of these file, which is going to be a file from our system. In fact, I can tell you right now that it's partial file. At the moment of recording this video, obviously blob, it's going to be webkit relative path string. So that's the type of this file which is from our computer. Okay. But as I told you, I don't want to complicate myself for only for satisfying TypeScript. Okay, so this is going to read files from our system. And it's going to return an ID, a name, a code, and extension, and a relative path. So basically it's going to return a user file like this one. Okay? And also one last thing that I wanted to tell us that we're not going to make a test for these only because these ads, it's a complicated has because we have two mockup file from from our system and make it work with a FileReader class, which we're going to see in a moment and things like that. So yeah, I don't want to complicate my myself with a test here. So this ONE probably one of the few things that we're not going to test. Okay? So this is going to return the new promise. And a promise as a result from our object. Right now are only going to have it herself. We're going to say const reader, new file reader. So this is a class that is built-in with note. It says let's web applications or synchronously read the contents of files or raw data buffers, the stored on the user's computer using file or Blob object to specify the file or directory. So here we're going to want to say a reader read as texts. And we're going to pass the file reader dot onload. And here you can see that we have an error on loads are going to say ONE though. We're going to pass a function. And in this function from the file, I'm going to deconstruct two things. The first is going to be the name of the file, and the second thing is going to be the Web Kit relative path. And he had this name, maybe allele specific. And that's because it's specific, would keep the relative path is only going to work for webkit, which is an engine for browsers like Chrome, brave, I think also Microsoft Edge and Opera. Okay, So probably this is going to work for Firefox and Safari. So that's a consideration you have to take here. But again, I don't want to complicate the course further just to satisfy Firefox and Safari. Obviously, if you're going to deploy to production, you obviously need to do that. You need to make some research on how to read files in Firefox and Safari. Okay, so now we need to generate an ID for these file. And for that, I'm going to install a package called UUID thing. We haven't installed it yet, so let's run npm installed UUID. And this is going to allow us to create unique IDs. So in the meantime, let me import. So before is a type of ID that we can generate from this package. And people tend to import it as UUID before from each ID. Okay, and so here we can say UUID before. And that's it. We have generated our unique ID for this file. And then in the code, I'm going to say Reader dot result. And here we can make, how can I say this safety measure by saying type of these is equal to string? Yeah, we say radar dot result, otherwise an empty string. So in theory, reader dot results should always be a string or an array buffer or no. So if it's an array buffer or no, then we're simply going to say an empty string. But if you're important code that should always be a string. If you're importing things that are not code, then it can be probably one of the things here. So that's why we're making these this type assertion here. So we've got to have that security, extra security measure again. And now we're going to get what else? The, the name of the file split or I'm going to call this viral spread name. And I'm going to say name dot the split with a point. So this name here is going to be something like index.js. Name is going to be something like index.js and webkit. Relative path is going to be something like source index.js file. Let me put this current here. Okay? I'm going to say examples of name and a webkit relative path. Okay? So the splitted name in the first, the first element, because this is going to return an array, is going to be the name of the file and the second element is going to be the extension. So I'm going to say extension is going to be equal to split up name. And I'm going to say split the name dot length minus one. Okay, just to be sure we have everything for this to work. So now we resolve this promise by returning the ID, the name of the file, the code, the extension, and the relative, which is going to be the webkit relative path. Okay, so that's it. We have all went and we can also get from the promise to reject. And we're going to reject these where we have an error. So either an error, it's going to be a function that receive an error and we're going to reject with this error. Okay, So that's it for this file. And why we have put this in a separate module here. Well, because we want to mark these read file function when we make tests for our hooks. Sorry for our thunks, which is the next topic that we are going to review here. Okay, So this is everything you need to do in order to read a file from your computer. I hope you like it. See you in the next lecture. Bye bye. 31. Understanding FileViewerStructure Type: Hi and welcome back. So the purpose of the following videos to create thunks, to open a file, close read files. Obviously right task for them. So first of all, we need to know what banks are, right? And for that, we first need to understand what are we going to do in the UI. So in the UI, we obviously want something like this, something like what we have in VS code, these folders and files and subfolders. So for that, we're going to use a tree view, which is a material UI components. And as you can see here, at review, we did presents a hierarchical list. And they can be used to represent a file system Navigator, which is exactly what we want to do, is play in folders and files are nighttime representing a folder can be expanded to rebuild the contents of the folder, which may be file folders or both. Okay, So we have here a simple example and Applications folder with the calendar document, which has a sub folder called material UI. And it has an index.js file. So this is exactly what we want in our application. So as you can see here in example, we have a tree view and the view has nested items. So it has an item with this node ID and a label. And inside the striatum we have another tree item. So we have nested tree item, and that's how we nest folders with sub folders and files. Okay, but we have a problem here because when we import our directory, we don't know the structure of the directory. We don't know. I've had has hominins, Apollos has how many files are in those folders, et cetera, et cetera. So we need to make it more dynamic. We can't just hard-code things like this. If we go, if we scroll down, we also have multiple selections you can see and this is what we want here, the object. So while the tributary item component APA maximizes flexibility, an extra step is needed to handle a rich object. So let's consider that a parable with the following shape recursion can be used to handle it. So here I have the data, the ID root name parent, children. And these children and youth also come how? Children and things like that. So this is what we want our file viewer a structured to be. Okay? So these will be the result and these will be the components. So here's data. Has children. The children can have sub children again. And basically, what we need to do to accomplish that is to have district you with these render tree, which is going to be a recursive function. And that recursive function is going to be this thing here. So it's going to be a tree item again. And we're going to take inside here, if these node has children and if it has children that we call again the render tree. And if it doesn't have have children, then are going to return law. And I will be like our base case. So for example here, this node here, ID1 named Cao Huan. It doesn't have children. So basically we're going to say, I'm sorry, we're going to render null as the children of the striatum here. Otherwise, if it has children like I like this one, ID3 named child, three children, then we're going to continue with the recursion and make a map and make the recursion again. Okay, so that's what we're going to do in our application. Okay, so let us start creating that type because we're going to use that in our app. So inside files, let me export the another interface which is going to be called by your structure. And it's going to have an idea, as in the example here. It's going to have a name. It's going to have children, and that is going to be optional. And the children is going to be an array of file viewer structure. So this is something that you can actually do in TypeScript. So reference, these interface here, recursively game. So that's going to be the structure of our reach object as you can see. And additionally, we want another thing here which is going to be optional. And that is going to be the extension. Okay? So this is going to help us to render the icon that we want to show for the file. So for example, here in VS Code, you can see that file.txt. We know that the extension is ds, so we need to render this icon. So that's why it is going to be also useful here. So that's it. I want to show you what this file viewer structure is and where did it came from and how we're going to use it with this material UI component. So after you understand this, then we're ready to start creating our thoughts. So that's what we're going to do in the following video. See you in those videos, Bye bye. 32. Creating OpenFile Thunk: Hi and welcome back. So now it's time to understand thoughts. Before we do that, I thought of a better name for these probably crave your name. Trivial node is a better name for this. So I'm going to make that little change, make sure to do to reflect the change as well. Okay, So let's create inside the store a new folder called phones. And inside plants. I'm going to create the first, which is going to be open file. And here I'm just going to say up and file.txt. And in the next video we're going to write tests for this thing here. So what is open file? So this is different from reading a file, opening a file. For example, when I click here on these index.js, then it will do two things. It, you add the file to the active files and it will set the editor active file to that idea of this file. Okay? And if the file is already in the active files, when, then we are going to do anything, we're just going to set the editor. I defiled to the idea of these file. Okay, so that's basically what the bank is going to do. So what's so special about this? Well, for doing that, for adding a file to the active files in the redox state. And for setting the editor active file, we need to actually dispatch two actions, right? So a funk is basically a function, okay? The function can receive whatever parameters you want. In our case, for the open file is going to be a node. That's why I renamed this thing. In the types are in the era name it to achieve you note, because we are going to receive a note, trivia note. And that thing that this function which receives note, attribute node is going to return a color. And this callback is going to contain all of these logic of dispatching multiple actions, et cetera, et cetera. Okay, so although we can do inside the component, it's better to use a thumb and put all of these logic inside. So let's start writing that. You're going to understand this better if we simply read it. So I'm going to say export const up in a file. And as I said, this is going to receive a node and that is going to be a tree view notes. Perfect. And as I said, this is going to return a callback. So what does that mean that this function is going to return a, another function in other error function. Okay? So something like this. Okay? And here is where we're going to put all of this logic of this pattern, multiple actions, et cetera, et cetera. So in this new callback glue, we're going to return. We actually need to get to things. Okay? That is going to be the dispatch, which is going to be of type AB dispatch. And also get a state which is going to be an a callback that returns the rotor state. And we also need to import that. Okay, So this is the function signature of the callback. Okay? So here now we can do lots of things. But before we do that, I wanted to make a clarification here. So if we see the app dispatch type, you can see that it's a complicated thing, right? It's a tank from dispatch, which has the stack here and it intersects with another fungus badge and intersect with a normal dispatch. So what does this mean? Well, it looks complicated, but actually it's not. It. This means that this Dispatch can do actually three things. Again, it can dispatch an action. So that's, sorry, that's this last thing here. It can dispatch in action. Just well, we haven't done that yet, but we're going to see that we weren't going to do that. So it can dispatch a normal action or it can dispatch a synchronous or an asynchronous thank dispatch. Okay. So if we were to put here, for example, something like a async await syntax, something like this. We will need an asynchronous. The funk and redox toolkit allows us to do vary something like that very easily with and create a thunk. But here we're just going to do some synchronous. We don't have to worry too much about that now, by the way, are going to create an asynchronous function later. Okay, so that's the app dispatch type, what these objects batch type means space. Okay, So just for clarification there. Okay, so here I'm going to get from that node. Okay? We're going to get the ID and also the children. Okay? And these ideas, I'm going to rename it. Yeah. No, I'm not going to rename it. Okay. So if if the children exists, has children, then we're going to simply return. Because if that, if the, if the node has two children, that means that it is a sub-folder again, so if we go back to our example here, where's Ridge object here? So here, as you can see, these ID3, main child, three children. So this is basically a sub folder. Okay? Well, women have an example here. We have here. So if we click here, we click here. We shouldn't open any file because there isn't any power, right? So we just want to return and do nothing. So that's what these are return means. And if the, if the node has no children, then we have to do or things. So first we're going to get the state. We're going to get the state. And from the state, I'm going to get the files. And from the files I'm going to get the active files ID's. Okay. Then we're going to check if active files ID, that includes the new file, that the idea of the node. Okay? So actually if the inverse of this condition, so if active files ID's does not include the id, then we are going to dispatch an action like this. Act the file. And that remember comes from a store, slashes licenses, latch files is large files. So remember, let's go here, not here, where we are exporting these action careers. So we want to create this action with the payload of the new ID. Okay? And last, lastly, we want to dispatch another action, and that is going to be the set editor active action. We've IV of the new editor, active file. And that's it, that this is our thunks. So as you can see here, we are handling some logic. I wouldn't say complex because it's pretty easy. Okay? And here we're saying, Hey, the active files ID does not have this idea that I'm passing you, then added to the active files and finally, dispatching other action to set the editor active file. So that's basically all of the complex logic that we want to encapsulate inside it. Ok. And assigned lets you do these dispatching multiple actions and making some complex logic, etc, etc. So this is basically the, this is the thumb. And well, obviously in the next video, we're going to write tests for these. So you can have a clear picture of what's happening with this tank here. Okay, so I hope you liked this video. See you in the next lecture. Bye bye. 33. Adding Tests For OpenFile Thunk: Hi and welcome back. So now let's add test for these. Open the file. Sunk. We're going to do it as JavaScript file again. Or not complicated. Complicating our lives with types, with TypeScript. Okay, so let's import from the open file. Let's import Open File. And let's put a describe block up in the file. I'm going to say let Dispatch unless you get a spade. So why we're doing this? Well, basically, we're going to mark these dispatch and get a state. We don't want to use a real dispatch and gas did from redox. So before each are going to say this batch is equal to Fn and get the state is equal to just FM. So basically we're saying that these dispatch and get a state are going to be these mock functions. Again, we can make implementations for them in each test. Okay, so the first test is going to be, it should not open. Note if it has children. Okay? So that's the easiest thing to test. We're going to create a node with an ID of one. And children. Again, children is going to like this. And this is cool about making our test with JavaScript because we'll need these node to actually be the preview. Note that will only complicate our test allele bit more. Okay, Now we're going to call this up and file function with a note. And this is going to return a callback, right? So we can execute the callback. And we need to pad to them to pass through that callback, the dispatch, and GetState. Okay. So that's it. Now, what how are we going to know that this was these children was not opened or something like that. Well, basically, we can make sure that these dispatch was not executed. It was not called. Okay, so we can say x, this batch not to have been called, to have been called. And we can also do the same thing for get a statement. We can say that get a state not to have been called. And if we did that and run npm test, let's say. So yes, our test is passing. So let's add two more tests. So the other test is going to be, it should open than node if it is not already open. So that case will be, we are going to dispatch this thing here. And we're also going to dispatch this thing here because if active files ID does not include the ID, that means that the node is not already opened. Okay? So for that, we're going to say get the State MCH return value. And then we're going to return files, which is going to be an object which contains active bounce ideas. And that active files ID's is going to be an empty array. So it is not going to include anything in the active files. Okay, so now we can say that the node is something like these. Id1 again. And now we can open the file with a node and passing the dispatch and the GetState. Okay? So in this case, I expect this patch to have been called two times. First here and then here. So that's easy. Are going to say expect dispatch to have been called times 2. So this means we call this thing two times and the test is passing. And we can even be more specifically if we say expect this patch mock calls. So these are going to, let me make a console log of these so you can see what is this dispatch that mark that calls. So as you can see, this is an array of the calls of dispatch. So if I say calls, if i mean unexpected statements saying is patch, that Mach calls, and I get the first element, which is going to be this thing, this thing here. I can say that this needs to equal this array here basically. So let me just copy. And now this is like cheating, but you get the point. Okay? And the test is passing. And I can make the same for the second call. So it's like this and something like this. Okay? So let's see. In the first call, I'm calling these action, which is the active pile action. Okay, perfect. And the payload is one. So basically the node id. And in the second dispatch, I'm calling the set editor active file with a payload of one. So that's basically what this test is asserting. And it's correct. That's our expected behavior. Now let's have another test. Is going to be the last test. And it's going to be each. You'll open the node if it is already opened. Okay? So in this case, we're going to copy and paste this. And here we're going to put in the active files ID's are going to put a one. Okay? So now the test is going to fail because it only makes one call and that's expected because this condition is not going to be met. So we're going to skip this condition here. So now we need to have been called times1. And the first assertion is actually going to be these ones. So let's change this one to 0. And now our test is passing. Okay, so now the action type is set editor and the payload is one. So we're only dispatching these action here. So I guess this is all of the cases and the cases are covered with these three tests. So we have 100% coverage on these punk. And that's it. That's basically a funk. Now you know how to test apart, which is pretty, pretty important because this, at the end of the day, contains all of the logic to open a file in our editor. Okay, so that's it for this video. In the next videos, we're going to create the thunk to close a file. Hope you liked this video. See you in the next lecture. Bye bye. 34. Creating CloseFile Thunk: Hi and welcome back. So we have created the funk for opening a file. Now let's create the thumb for closing a file. Or I'm going to name this close file. And we're going to create a new file called file.txt. Okay? So this is going to be another synchronous, OK. And we're going to call it close file. And this is going to receive the file to close ID. And it's going to return a call back. Remember that callback should get the dispatch which is of type up his badge. And should get, get a state, which is a callback that returns route the state. Okay? So let's see. Here we're going to implement the logic. So first of all, let's get from, get a state where you're going to get the app, the files. From the files, we're going to get the active files ID's and the editor active filing. And we're going to get the active files a length. And that is going to be amplifiers. I did LatLng. Okay, so we have four cases. So you can see here. So the first case is when we have just one file in our code editor game. So in these space here, we just have one active file. In that case, if I close the file, like right now, what we have to do is to set the editor active file to know because there's no file to set us up. So that's the first case. Let's do that. Active files length is equal to one. Then in that case, I'm going to dispatch an action. And I'm going to say set editor active file too long. Okay, so the set editor active file, remember, comes from the file. Okay, so that's the first case. The second case is when I have more than two files. So for example, this one and the file, the active file is the one that I am going to close and it's at the right most place. So for example, in this case, if I close this file, then I go to the left file. And also the other case is when the active file is not in the rightmost place, but here. In that case, I get here, but we're going to make it go to the right file. Okay? So let's say that for that, that condition is going to be active. Files length is greater than or equal to 2, and the file to close ID is equal to the editor active file ID. Okay? So in this case, we need to do something more complicated. Okay? We need to get the ID of the file to the left or to the right, depending on where is the active file. Okay, so for now, let's, let's code the rest of the logic. After we do this, we need to dispatch another action, which is going to be the remove active file. And we need to pass the file to close. Okay, So this is going to remove that ID from the active files array. Okay? So here, first we are going to get the new active with a function that we're going to write below this function. I'm going to name this function, get new active fire ID. Okay? And this is going to receive the active files ID's an array of strings. This is going to also receive the active files length. So we don't recalculate it. And it's also going to receive the file ID. Yeah, the file ID or file to close a, which is a string. Okay, so once we're going to do here, first, we're going to get the file to V, remove index. Sorry, this should be like this. File to remove index. We're going to get that from the active files index file to close. Okay, now we have the file to be removed index. Now we need to consider the case where the file to be removed index plus one is equal to the active files length. So this case will be, these happens when the active file is at the right place, is or is the right most top, whatever you get there, the idea is the last tab to be closed. So this is the case. Then we're going to return top of the left, which is going to be active files, ID's file to be removed, index minus one. Otherwise, we're going to return the top to the right, which is going to be active files, ID's file to be removed, index plus 1. Okay? So now here in this else condition are going to say const new active file ID, new artifact ID. And we're going to call that function get new antiphonal ID. We pass the active files ID's. The active files length, the file to close. And then we dispatch the set editor active file to be that active. Okay, and that's, that's all of the logic for closing a file. So as you can see, it's a little bit complicated. Closer file, but that's what we need to do. Okay, so now we're going to write tests for this function. And that's what we're going to do in the next video. I hope you like this one. See you in the next lecture. Bye bye. 35. Adding Tests For CloseFile Thunk: Okay, so it isn't that easy to close a file. So let's create a test for this. Especially when we have a logic like this, we need to test it. Okay, so I'm going to copy the test from Open File here, and I'm going to just remove everything here like that. And obviously change these File, Close file. And here. We shall also replace these two close file. Okay, so we're going to write for tests, and these four tests are going to cover all of the possible pieces. So the first task is going to be close, The only active power. So that happens when we only have one file. So for GetState, I'm going to return a value. And I'm going to say of piles, active files, ID's. So in active files or D, we're only going to have one file with the ID of one and the editor active file ID is going to be one. Okay? So now I close the file, Close file. We pass the file to close ID, which is going to be one. Remember these returns a callbacks are willing to call that callback. And we pass that this patch and get the state. So we do this, then we're going to expect to dispatch to be called two times this and this. So let's expect that this patch to be called times two. Okay? So let's see, this test is passing. Okay? Yeah, the test is passing. So let's now make the assertions on the calls of the dispatch. So we're going to say this patch mom calls. And remember this is an array of arrays. So this will equal to equal. And the rain with an object, with a type and a payload. So the type is going to be files slash said, editor, active file, and the payload. So that corresponds to this call here, right? So let's see if our test is passing. Yeah, it's passing. Now let's make the second call, the assertion on the cyclical. And that will be with a remove active file, remove an active fire. And the payload will be the ID of the file to be closed, and that is one. And that test is passing. Okay, Now let's make a test for when there are more than two active files. So I'm going to put another describe block and when there are two or more active files. Okay, and here we're going to have three tests. The first one is going to say it should remove, remove the other files. We are not closing the editor active file. Okay? So this corresponds to the case where we don't hit any of these conditions, don't hit this condition and this condition here. So if that happens, then we just call dispatch. One's, right. So let's say get a state, my return value, files, the files that are going to say 1, we have 1 and 2. And the editor active file ID is going to be one. And then we're going to close the file to be passed this batch. So if you are understanding this correctly, we have distractive house and we are currently in the file one, but we're going to close the file two. So in that case, we are only going to call Dispatch wants. So we're going to say expect dispatch to be called times 1. And we're also going to make an assertion, assertion on that call. So Dispatch calls 0 to equal an array with type equals two files. Remove active file. And the payload is going to be the file to be closed ID, which is 2. So let's see if our tests are passing. Yeah, our tests are passing. So let's make two more tests. Okay? So the first way we're going to have two more tasks. The first case is when the new activity is the rag most tab and the other is when it's not the rightmost tab. So let's say it removed the editor active file ID and set the new editor, sorry, the new editor, active via ID to be the one, to be the one on the right. So that's a long description for the test. But I hope these words, so let me just copy and paste because the task is going to be pretty similar. So here we have 12 and the editor active file is one. And we're going to close this time 1. So this time, this part is going to be called twice. And the first, the first action that is going to be dispatched, sent editor active file. And the set editor active files sent to to be that edit profile. So that's correct. And the second calls should be the Removal Act, the file with a billet of one. Okay, so the tests are passing. Now let's make a copy of this test and let's, let's modify the title of the test. We're going to say it show removed the editor active file, uncertain item, ID to be the one on the left. Okay? So right now what we're going to do here is instead of closing the file number one, are going to close file number two. Okay? And yeah, the editor active, these are going to be two, and that is the one that we are going to. That's the one we're going to close. Okay, So this time it's going to be called twice the dispatch. But the payload is going to be now one and remove artifacts. The pellet is going to be two. So all of her four tests are passing. So now I think we have 100% correct on these. So yeah, it's a little bit complex, and that's why tests are so important for this type of thing. So I hope you liked this video. And I hope that with tests, you understand the better these functions, all of the logic inside this function. And see you in the next lecture. Bye bye. 36. Creating ReadFiles Thunk: Hi and welcome back. So remember that we created the read file function to basically read a file coming from the input. So now we need to create a which is going to be called res files. Okay? So let's create this read files function, okay? And this is going to be an asynchronous function. So remember here we're all putting. So these will be synchronous logic. Now we're going to put asynchronous logic. Okay? So for that, what we're going to do is the following. We're going to export const, read files. And we're going to use these function that comes with redox toolkit, which is called create a sync thumb. Okay, So we pass basically the name of these func. We're going to call it files as lash read files. Note that we didn't do that here. So if we use redox toolkit, we're not going to see something like files slash close file, but rather we're going to simply see the actions that are being dispatched inside this function. But here, well, this will let us know that we are dispatching these read files. We're going to see how well you write the test or unwell. We see them in the UI again. So the second argument to the greatest Funk is going to be an async callbacks. And the first argument is going to be whatever you want. So I'm going to put files, which is of type file lists. Okay? And this is a type that comes with TypeScript. And you can see here that it's an object of this type, is returned by the files property of the HTML element. This lets you access the list of file selected with the element is also used for a list of file rub into web components when you send a drag-and-drop API. See that data transfer objects for details on these usage. So this also is used for when we upload content from the input. Yeah, from an input which we're going to see later. How to do that. Okay, the second argument is going to be the thunk API. And this API basically some object that we can get dispatch. Think we can also get GetState. In this case, we're only going to need dispatch. Okay? So we can get this fetch from the subject. Okay, Now what we're going to do, we're going to create an array of promises. So each element of this promise is going to be the read. The problem is that is returned by the read file function. So remember, this function here returns a promise. Each element of that array is going to be that price. So let's create promises. And Let's make a for loop here. So for let I equal to 0 until files that length and we increase, I are going to say KMZ file is going to be files. And then we're going to say promises that push ILO are going to get that read file function. Here. From here, we're going to bias the file. Okay? Now we need all of these files to start all of these promises, tourists. So what we're going to do is say const, user files is going to be await, promise that all we're going to pass all of those premises. So this is going to resolve. Once all of those promises resolve. And last but not least, we're going to dispatch the files. Action. We need to put the user files here, and that's it. That's everything we need to do to read the files. Obviously, this is going to be used in a button. Okay? So before we create the button, we need to handle all of these logic here. Why did I put this red fire here and not here? Because I could copy everything here and put it here. Well, the reason is because in the next video that we're going to write a test for this. We need to make these readFile because remember we didn't write a test for this. So we need to mark this and make it resolved something with this format here. So that's why I need a way to mark this. Okay, So without further ado, let's try to do that in the next video. Bye bye. 37. Adding Tests For ReadFiles Thunk: Hi and welcome back. So we're going to write a test for this again. So read files that test.js and these stats hopefully is going to allow us to understand better how a single Thanks work. Okay, so let's import, let's import, read files from this file. And it's also important to read the file from utils slash RET file. So an important difference here is that we're going to mock utils slash readFile. So why we're doing this? Well, for the same reason that we didn't write a test for this thing. So now let's write describe log files and let that get a stained and do the same before each are going to sign this batch to just that and, and get the state to jazz. Okay, so we're only going to write one test here. And that's going to be, it should read two files. And our test is going to be a synchronous. Ok. And let's see, we're going to create this user files object array, which is an array of objects. And the first file is going to be the one named index.js. Code is going to be whatever cost of luck, Hello World, the extensions or is it going to be the relative path is going to resource index.js. So that's our first file. And let's make another one like this. So let's change this to mangers and this source maintains. Okay, Perfect. Now, when, when we mark these a read file function, we need the first time we call it to return the first, the user file. So this thing here. And the second time, we need to return this thing here. So how do we do that? Well, pretty easily, actually, we say a read file, a return value. And we're going to say user files of 0. And the second one is going to be user files of one. So basically what we are telling here is the first time you invoke this function, then return these. And the second time you return this function, return this. Okay, So that's how we do it. Then as this is an asynchronous function, we need to await read files and we need to pass files. So let's see here we're we're passing files and yeah, we get the files length. And then we use these files to put it here. But actually, these fire is not an important role because the result of which file is marked. So the only thing that is important is that the length. These files array we're going to pass is two. So for that, I can pass the user files if I want, or I can pass any other, any other array with two elements. Something like this will also work. So yeah, I'm going to pass user files. So or you can put whatever. I'm just not sure what the past year. So we're going to pass again dispatch and get a state. Actually, let me just change this to be whatever. The reason behind this is. We don't want person who's reading this and say, Hey, we interpret this user file, read files, and that doesn't make any sense. Yeah, it's just a thought I'm having right now. Okay. So now we need to make an assertion on the dispatch. And this time we are going to expect dispatch to have been called three times. Three times. And you're going to say why we're only dispatching an action here. So that doesn't make any sense why we're here, why we're expecting this patch to have been cultured times. Let's see if our test is. And yeah, our test is passing. So what is happening here? Well, let's go and console log, dispatch that Mark calls. And let's see what it returns. So as you can see these returns three calls. The first one is this action here which is of type files as lash read files as lash pending. So that's why we pass in here so that it can construct these action which is fast slash files slash spending. The second one is the actual dispatched we're doing in our code. So SHE said files. And the third one is files slash files slash full field. Okay. So what are these two actions that are dispatched for us? Well, that's the magic of creative. If we were doing this with normal redox, we still will need to do this. If we wanted to think, well, you obviously ignore them and that will be also acceptable, but that wouldn't be a good practice. So this action pending, as the name says, is for learning the redox. Know that we are pending and that we haven't finished yet. So for example, if you are fetching data, then probably you want to put a spinner or something like that in your UI. Okay? So for that, this action is going to be dispatched and you can create the reducer for this action and that reuse or you can set loading to trooper, for example. Okay? And then when this is fulfilled, that means that everything went well. And you can set that loading to false again. And there's actually another one, I think it's error. You can, for example, set a narrow object. In fact, let's go at the documentation three distinct tongue relax toolkit to see if we can get more information here. So you can see the overview says a function that accepts a redox reaction type string and macabre function that we're trying to promise. It generates primase lifecycle action types based on the action type prefix that you passing and returns a bank actual creator that will run the premise callback and dispatch the lifecycle actions based on the return promise. So let me see if we can find the, yeah, here we have the types. So we have bending, we have fulfilled and we have rejected. So this is the one I was telling you about. So you can make reducer for this action and set an error object there. So actually this is a little bit more complicated than that. I synchronous a funk. So let me see if I can find something. Yes, So here for example, we are getting this fetch user by ID. We are making a reducer for that, for that type of action. And yeah, you can see that this is allele little more complicated. So I recommend again to go through all of these documentation to learn more about creative. Okay, so for now we're only going to use it like this. We're going to make a test. So in the first goal, remember, it's going to be, sorry, it's going to be this array here. And from that array I'm going to get the first object, and I'm going to search the type of the property, type 2 equal 0 first, let me make an expect here. To equal. It's going to be files, read files slash bending. Okay, so that's going to be the first assertion. The second assertion is going to be dispatch that mark that calls the second thing. And this is going to be actually our dispatch inside there, this logic, So this one. So it's going to have a type of files slash set files. And the payload is going to use our files came. And we are going to also have this patch that Mach calls to 0, time t equal files slash files slash full field. Okay, so that's it. Actually you can make it another test that's going to be an exercise for you. So instead of making these readFile to make a return value ones, you can make these redact. So throw an error. And in that case, I guess you're going to have the file slash, files slash rejected. So you can do that as an exercise. And that's probably going to make you understand things better. As you can see, they are a complicated topic, so we're going to use it as simple as possible. Just like this. I guess, I hope you liked this video. We are very close to start building the UI for the file viewer tree. And yeah, I hope you like this video. See you in the next one. My way. 38. Adding Tests For SelectTreeViewData: Hi and welcome back. So I think this is the most difficult part of the course because we're going to develop an algorithm that is going to take our user files and convert them to the tree view structure that we saw here in this material UI component. So it's going to take a user piles array1 and it's going to turn it into this dynamic data structure. Okay, so let's create a new folder inside selectors and we're going to call it select Preview data. Okay, Animal are going to follow TDD here. So select the data the test suggests. So first we're going to write the test. And the test is actually going to be a little bit difficult for this one. It's just going to be one test. That is going to say it shall convert an array of user files to that tree view data structure. Okay? So, yeah, Let's write this user files array. And this is going to have six items. So the first one is going to have ID1, Name Index 1 dot js X. And we're going to say around if bad is going to pull task as slash sub-folder as lash in other sub folder slash index one that JSX. And I'm going to escape the codes property here and just use the extension. So I'm only going to include those four things here. So these, Let's start writing also now the expected results, but we didn't get confused later. So expected results should be something like this. First of all, the idea of the root should be any string. So we're going to expect here any string, because the folders don't have any string, so we have to generate them. And for that we're going to use the UUID folder, sorry, the UID package. So the name of this folder is going to be test and this is going to have children. Okay, and that's going to be an array. And the first item of these children is going to be these subfolder item. So again, the ID is going to be any string because the folders are going to have auto-generated auto-generated ID. The name is going to be subfolder. And this is going to have children. And these children, again is going to be another subpolar. So we have to say ID. I can expect a string. The name is going to be another sub folder. And again, this is going to have children. And now we can write the children, which is going to be these index1 that JSX file. So this time, this does have an idea which is the ID1. The name is going to be index 1 dot js X. And the extension is going to be perfect. So I know this is for just one item. This comes to be very complicated. But let's start writing more items. So we have a lot of confidence in what we're writing here. So the second item is going to be ID 2. It's going to have named index.js jazz. Our relative path is going to be something like test subfolder, index.js and the extension is going to be Jess. Okay? So where do we put this? Well, we have these subfolder children. And inside this subfolder children, the last item shall be this index two dot js. So let's write here ID. This time is going to be to, the name is going to be indexed to dot js. And the extension is going to be J S. Perfect. So now let's write another item here. This is going to have ID3 of a name is going to be index 3 dot js. And their relative bath is going to be test slash sub folder to slash index. That. Yes. So where does this item and extension also is going to be just so where does this go? Well, it goes. We have to put this inside tests, so entitled children of tests. The last item of these children shall be another. A sub folder, so it should be sub folder too. So we're going to say expect any string, the name is going to be subfolder two. And this is going to have children. And the only element the inside these children is going to have IV. It's going to have a name of index 3, 3 dot js. And yeah, the extension is going to be perfect. So let's add three more items. Because I want this to be as robust as possible, this test. So i d4 name index 4 dot ts. So let's change that to TypeScript file. Relative path is going to be test slash sub-folder 3 slash in other sub folder slash four, Ts. And the extension or is this going to be? So we have to create some folder three inside the children of these Test folder. So this is a first. Second. So here we're going to say id. Expect a string. Name is going to be subfolder. Three children is going to be one element. And this element is going to have any string as I as the ID. The name is going to be another sub folder. And the children is going to be lastly, the file, which is going to have ID for ID for the name is going to be index for the Ts and the extension is going? Yes. Okay. Okay. Now let's make two more. Let's make id. Name is going to be index five ab.js. Relative bad is going to be tasked to slash index dot js. Extension is going to be js. And let's make one very similar to this. But this time I D is going to be 6. 6. And yeah, we're going to change this to index six, that view or view files. Okay. So let's make sure that these are included in the children of tests of these children is the last element. So here I'm going to say id 5. It's going to be the name index. Index 5, that jazz. And the extension is going to be JS, of course. And one more. Here, I'm going to put in IV, name, index.js and extension. In that view. And extension is going to be view. So now we have a pretty, pretty robust tests. So we take this user files and translate it to this tree view data structure. So we need to also import select, Preview data from some data. Okay? So obviously we don't have anything right now. And at the end of the test, we obviously need to make assertions and experts select attribute data. And here I'm going to pass the state. And we haven't specified yet to equal expected result. So the state is going to be very easy. Actually. It's going to be files, and these files is going to return the user files just like that. Okay, so now we need to make this test. And that is going to be the challenging part. So both running the test and make it this thing that is a challenge. So just let me double-check that. I didn't mess up with extensions here. So in this one but yeah. Yes. Yes. Yes. Yes. Ts, ts ts jazz UUU. Okay. So I think for correct this x gs, Ts, gs, and you. Ok, so everything looks correct. So in the next video we're going to write this function. So you in that video, Bye bye. 39. Adding SelectTreeViewData Selector: Hi and welcome back. So now let's write the complex function here. So let's create the tree view data. And this time, again, I'm going to do it for us JavaScript, because it's a little complex. I don't want to complicate my life here too much. So first, let's create the select file or tree view data. And this is going to receive, remember the user files from the state. Okay, so how do we do that? Well seems that we export default, create selector. Okay, great selector. And we pass the state and the state that files a user files. So that's the argument for select trivia data. Okay, so now let's write the logic for this thing. So let's go and declare this result object. So this is the thing that we're going to have here. So this is going to be the expected result. Let's make a for loop. So for lead I equals 0, I less than, sorry, I less than user files that length. And I plus, plus. What we are going to have here is first get the user file. So here's our files of I. Okay? I'm now these user file has many things, right? It has, first, it has a name, it has a relative path, it has an ID, and it has an extension. Perfect. So now this relative path, we're going to split it by e is lashes, and that is going to give us an array called patents. So pets is going to be relative bat, a splitted by this slash here. Okay? And yeah, probably you, probably this is going to be different than the windows, but again, that's an exercise for you. If you're a Windows problem when this is going to be something like this. Okay. So yeah, although I'm using Windows, you have to know that I'm using Windows Subsystem for Linux. So that's different. Okay, So now let j equal to 0. It's going to be our iteration index. For the thing that we're going to do next. We're also going to declare these current level viable, which is going to be equal to the result. Okay, And here comes the difficult parts. We're going to make a while loop. And the while loop is going to set it to two. It's going to see pats of Jane is different from the name. Okay? So while the path, so remember that the last element of paths is going to be the name. So while that doesn't happen, we're going to do the following. We're going to save path is equal to path of James, so we get the current path. Okay? And the first type that we're going to do is if Arrays.sort drain current level. So if current level is not an array, so if it is an object and current level doesn't have an ID, okay? Well, we're going to do in this case is to assign an ID. And for that we're going to use that before as UID before from UUID. Okay, I don't want to, we're going to do here is say current level not IID is going to be you use the UUID before. So by doing this, we are assigning a random ID to the folder. Because if current level is not an array and it doesn't have an ID, well that means two things. A folder and that it doesn't have an idea that we have to assign it. We also have to assign current level that is going to be the path. And the current level that children, that is going to be an empty array. And we assign the current level to current level that children. We increase the iteration index. We continue. Okay. So in the next, the next tech that we're going to do is that array. That array. So current level is not an array, but it has children. So if this is a case, then we're going to say current level is equal to current level that children. And we increase the iteration index and we come to you. Okay? So if none of these thing passes, that means that the current level is actually a array and array. So if current level is an array, what we're going to do is first check if there is a sub folder. So we're going to say current level of fine. I'm going to say child, child not name is equal to the path. Okay? And these can either exist or it cannot exist. So if sub folder exists, what we're going to do is set current level two sub folder that children we eat. We increase the iteration index. Else, if this doesn't exist, we're going to push an empty array. We're going to push them to rate your current level. And we're going to set current level to that last, that last element of this array. So current level, current level dot length minus one. Okay? And that's basically it. Now, after we break from this while loop, then we're going to say costs file data. That is going to be the ID, the name, and the extension. Okay? And we simply are going to say current level dot push file data. Why? Well, because grant levels should always be an array after any any of these iterations here. Okay? And also take note here that I didn't increase integration index. Why? Well, because in the next iteration, then it's going to go to this condition. And it's going to create a new folder here. And it's going to enter, it's going to increase the iteration index in this condition here. Okay? So, yeah, that's basically it. Now let's make sure that this thing is passing. So let's write npm test. And let's cross our fingers that this thing is massive and it's not passing. So let's see what are we missing here? So it says that we are receiving on the fine. Okay? So maybe there's something wrong here. Our tests. So select View data to equal expected result. Okay. Let me take a look here. Okay, So actually there anything wrong with the test, just that I missed something here. So after this for loop, I need to return the results. Returned results. And remember that this was sold is being modified because here we're making current level equal to resolve and we're making all of these things in the current level. And as these is passed by reference, so these, and these are the same object, then the result is also going to be modified. So that's the only thing we missed here. And yeah, now our tests are very complex, test is passing. So as our test is very complicated, I am pretty, pretty confident that now this thing is working as expected. And well as you can see, it's not a simple function. So if you didn't understand it, make sure to read through the function. You can make your own test if you want. You can put console logs or you can put the bugger and run the test in fact mode. So you can see what is happening. Make sure you understand this. Because this is a very complex function I have to admit. Okay, So that's everything for this video. Now we're ready. We have, I think, all of the logic in order to start the building, the UI. Okay, I hope you liked this video. See you in the next one. They die. 40. Adding OpenWorkspace Button: Hi and welcome back. So I think we have everything in place in order to start writing the UI for managing files. We have all of these selectors to select the active files. The select Review data. Thanks, Which is in order to close file, open file, read files, et cetera, et cetera. So now we're going to start writing a component. Let's put it here. And here, we're going to say up and the Workspace button, that TSX. I'm going to use my snippet here. Okay? And yeah, in fact, this is also going to be JSX. And I promise I'm not going to start using JavaScript more. I'm not going to use JavaScript more last time. Because here, again, this component is going to be in charge of reading the files. And as I said, I don't want to complicate my life just for reading files and satisfying TypeScript. Okay, so here I'm going to import from material, UI slash material. And also from yeah, So actually let me copy this here. That's going to be something very similar to this. In fact, going to be pretty, pretty similar again, these components, we can make it a common components, so it can be used for all of those things here. Okay, so this is going to be cold. Open workspace style button. You can find a better name. Go ahead. Yeah. So open workspace style button. That's going to be open workspace. Okay? And we need to pass an onclick handler. Okay? Before doing that, I'm going to create another styled component. And I'm going to call it input file. And that is going to be a styled input. And basically this is just going to have display no, because we didn't want to display this input file. So you may be saying, Hey, if we don't want to display this thing, then why is it here? Well, because this input is going to be of type file and it's going to have a href. Okay? So the href, we're going to create it Here. We're going to call it Directory input. And we're going to use the use REF, hook, use href. And this comes from React. Okay? So this is going to be initially null. And now we said the href to be directory input graph. Okay? So we need actually another thing here that is going to be that directory to be an empty string and the web directory to be an empty string. So this is basically for letting us upload a directory. Okay? Now we are going to create the onclick handler. So onClick for the up and ML workspaces Styles button. So that's the directory input graph. That current not click. Okay. And these onclick handler, we're going to pass it here. Again. So what does this mean? This mean that when we click on this button, what we're actually going to do is to click the input file. Okay, so that's a trick that we can use in React. So basically we're clicking by clicking on this button. We're clicking on this input file as well. Okay? The button remember is just for displaying something because the input file probably we cannot give them, we cannot give the input file the same styles as bottom because they are, they are two different things. The buttons about him and input is an input. So it's easier to do it like this. And yeah, when we, when, when this thing changes, so we need to pass an unchanged. We're going to call the on files, uploaded, files uploaded. And this is going to be in a synchronous method. So let me pass this to the unchanged. Okay? So here we're going to make a try-catch. To catch. We're only going to make a console error of the lock and try it. We're going to make, we're going to get the files from the directory input ref dot, current, dot files. And here comes the funny part. We just need to read these files, right? So this is an array of files, is the final list. So we only dispatch. Yeah. And for that, we need that US have dispatch. So first, before doing this, Let's go here and get this batch. This budget is going to be used. Dispatch from those hooks of a store slash books. Okay, so we're going to await dispatch and we're going to get the read files. We're going to add the files to the read file. And that's it. That's everything we need to do in order to make about them. And when you click on that button, open your file management system and put all of those files into redox. So let's actually also put this optimal Workspace button. And that is going to be here inside this code editor button. So we're going to change this little bit. We're going to use that history hook. So US history from React router. I think we have it here, so let's use it, use history. And here we're going to say history, that location, that path. If this is equal to pad that home. Okay, then we're going to render this thing here. Otherwise, we're going to render the AP-1 Workspace button. Okay? So yeah, we didn't have these export the important, sorry, So let, let important open workspace button from open the workspace button. Okay. Yeah, and we have additional bracket here. So let's see what's the result of this. Let's npm start. Okay, Let's go here and wait for this thing to finish. Okay. There we go. Let's see we are again. Yeah, so here we have this workspace and sign out. Let's make a quick. So how do we fix this? Well, I think it's pretty if we just have to make, let's make this authenticated buttons container. And that's going to be a styled there. And this is just going to be display flex. Display flex. Yep. Yeah, we replace this div with these authenticated buttons. Container. A container like this. Let's fix this container. Container. Yeah, there we go. So let's see, let's refresh this page. Okay, So now they are like this. If I click here, it's going to show the code editor button. And if I am in the code editor, it's going to show this thing here. So let's go and make this like this. Actually. Let's put it like this. And let's go to Redux. Let's make it a little bigger. Okay, and we're going to see what happens when I open the workspace. So I already have these, which is a wrap-up of mine that is on GitHub. So let's upload it. And let's upload it. And let's see what happens here in the redox. So first of all, I have readFile spending. As you can see, there's anything that changes here because we didn't have any reducer for this. And then we have this set files. Okay? And now you can see that, let's see the state files. Let me make this a little bigger. So now you can see that this user files contain all of the files. There are 19 files. Okay. And yeah, that's it. We have successfully put all of our files inside this user files array. And here again, we didn't have anything. And yeah, that's basically it. Now we have all of our files in the store. So what we need to do next is to actually call that select Preview data. Would that insight preview component may make some tab labels, tab panels, a container, and make the custom Monaco editor, which is going to be the component that holds our whole tower code. So don't worry if you didn't understand that last part. Because that's basically the architecture of what we're going to do next. So I hope you like this video. See you in the next lecture. Bye bye. 41. Adding ExtensionIcon Component: Hi and welcome back. So now we're going to start creating the components related to the code editor. So inside components, I'm going to create a new folder called code editor. And here we're going to start with very simple one, which is the extension icon. And that basically means, for example, here in VS Code, this icon here is the icon for react because the extension of the file and with DSX, and if it will end with JSX, he will be the same icon, the same with the ass, JavaScript and cetera, et cetera. So let's create the extension. I conduct the attacks. Let's use our snippet here. Okay? And this time, again, I'm just going to copy and paste because we're just going to import lots of SVGs that we put here inside assets slash images. Remember, all of these SVGs are here that correspond to the icons of each programming language. Okay, so now I'm just going to create here, instead of a div, I'm going to put a switch statement, switch. And I'm going to say prompts that extension. And obviously I need to put the prompts here. So prompts. And I'm going to say type extension. I can prompt is going to be simply extension, which is going to be optional. And it's going to be a string, this extension. Okay? So now that we have the extension, first of all, we're going to put the default case, which is going to be in return, the default icon. And let me see if I default icon is going to be that blank file. So fault icon file. And actually I'm just going to copy and paste also be other programming languages because it's going to be the same, just changing the programming language. Okay, so, yeah. So here we have four, JSX and TSX. We're going to return the React icon for JS, and I'm going to return the JavaScript icon. Yes, TypeScript icon, CSS, CSS icon, et cetera, et cetera. So you want, you can add the more obviously, you just have to find an SVG of the programming language added here, important here, and made the corresponding cases. Also here, I'm just going to create a simple inline style. So as I've said in an earlier video, I didn't like it too much. Don't like doing it like this. But for now, it's going to work. So high bandwidth, 15 pixels, and that's his fault icon also going to be, It's also going to have that style. So that's basically it. Sorry for all of the copy paste in here. I don't do this too often, but here it's just a matter of making this case switch case statement and returning the corresponding SVG. So there's actually nothing too interesting here. And that's why I just copy and paste. Okay, so I hope you like this video. See you in the next one. Bye bye. 42. Creating FileViewer Component: Hi and welcome back. So now we're going to write the file viewer component. And the component is going to be this part here, for example, of VS code, where you have all of the folders and you can click on the folder and you can click on the, on the, on the facts. Okay, So inside code editor, let's create a new folder called file file viewer. And inside file viewer, we're going to create the file words.txt component. Let's use our snippet here. Okay? And yeah, first of all, we need to install a new package called material UI as Lash, our lab. I think I just install it right now, but you need to do it through because we haven't done so. So just run npm install material I slash lab. Okay? And then you're going to have access to them and to the preview components. Okay, So to do, you're going to have our system trivial and China. Okay? So after you do that, let's import a bunch of things that we're going to use here. So we're going to port first from material UIs, last lab are going to get a preview and also create them. Okay. Let me see, just one thing. Okay. We're going to also import a style, import styled from UIs latch materials slash styles. Okay. What else are we going to do? We're also going to import this folder Open icon from material you eyes. I guess Materials folder often are also going to import folder icon from material UIs, icons material as lash folder. What else? We're also going to use from store slash hooks. We're going to get the US dispatch, the app selector. Also we're going to get so lag. Free view data from a store slash selectors slash select Preview data as lash, select Review data. What else? Let me see. You are also going to get the review notes, preview on node from type, type slash files. And we're also going to get the extension icon that we just go to the last video. And last but not least, we're going to get the open file thumb. Okay, So we have imported a bunch of things that we're going to use in these components. So let us start using them. First of all, we're going to get the viewer data. By doing this, use absolute vector. And we pass the selector, which is a select few data. Okay, So as I said, with this selector, we're going to be able to cache the result of this thing. So basically, if the user files don't change, then that use app selector is going to be as smart enough to return the same result each time. So that algorithm that we use to calculate all of these things is not going to be a problem because, you know, this is going to be cashed. Okay. So then we're going to use these dispatch, the US have dispatch. And then we're going to create these on select. Okay? And these basically is going to receive a node which is going to be of type tree view. And this is just only going to dispatch the open file. Thank within node as an argument. Now we're going to also create the render tree recursive function. And this receiver knows and the node is of type node. And that node, we're going to get the ID of the nodes, are going to get the name and the extension. Perfect. Now we're going to return the tree item component. So this tree item is going to accept many probes. For example, the key, the note IV, which is also going to be the ID of the node. The label which is going to be the name of The arm double-click events. So this is going to be something like this. Select note and we pass the nodes. And also the n. The n icon is just going to be the icon that is going to be next to the name of the folder, sorry, the name of the file. Next to the name of the file. Okay, so this is going to be the extension icon. And remember these, you have to pass the extension, which is going to be the extension of the note. So that's why we included the extension file viewer data structure. Okay, so last thing, we're just going to put some styles here. And again, these ESX property is we're adding styles and we can add big cells, Banning and a color. And this is the way of you that you can get the theme. So yeah, this has Sx property, the system prompt that allows the final system arise as well as additional CSS styles. So this is one of the recommended ways for mature you to put the styles too. Or two-component, sorry. Also you can make and it's tiled tree item if you want. But again, I don't want to make too many style components. So yeah, this is the only thing that we're going to do here in the tree item. Now we need to write the children for distributed. So remember we have two options here. If the node has two children, okay? Then we're going to render more trans. And this dragons are going to be rendered recursively. And even though it doesn't have children, then we're just going to render null. And that will be like the base case if we are thinking these as a recursive function. So we're going to say array that array, know that children. So if this is true, then we're going to see now note that children that map nodes render tree nodes. Okay? Otherwise we're just going to return null. We're just going to run their law. So basically we're saying if not Children's or an array, then iterate through each element of this array and rendered treat again. So by doing this recursively, otherwise return null, rather null. Okay, So we're almost finished. Let's now render the preview, preview component here. And the children is going to be the render tree with the file viewer data and also ok, so now we have a problem, a little problem here. It says argument of type object, empty object is not assignable to parameter of type 3 the nodes tab. Empty object is missing the following properties, id name and ID and name. So basically this is happening because we created these select Review data as a JavaScript file. Again, we didn't have any types on the result of this select Review data. So here we just have to tell TypeScript, Hey, did, believe me, we're going to pass a trivial node. Okay? Okay, so shoot a solved problem. Okay? That's a little trick. That's the trade off of not doing these electrified data in TypeScript. So what else? Yeah, so we need to also here add some styling. So I'm going to say padding is going to have some cutting like this. Pixels, ten pixels and pixels. The height is going to be 100% and the width is going to be 100 percents. Well, let's also include here the default collapse icon. So this is going to be the candle we're going to use when a folder is collapsed, that is going to be the folder Open icon. Okay? So when, when the, when the folder is collapsed, we show these icon. So the user knows that he or she is able to open that folder. And the default expand icon, sorry that the fault collapse icon is when the folder is actually opened. And so that's why I put folder Open icon here. And the default expand icon is when the folder is not opened. So we're just going to put folder item. Okay, so let's see what does it says here. I'll know what the error disappear. Okay? And one last thing that we are going to do here is when file of your data is actually an empty object. Now we're just going to return an empty message saying no files like that. So something like this. If object, file viewer data length. So if the length of this thing 0, then we're going to return. And here I'm just going to create a new style components saying const and the message. And the message that is going to be styled as style. And I'm going to pass a theme here. And I'm just going to return an object with a color being the theme. Okay? So here I'm just going to use this style components here, like this. And I'm just going to say no files, something like that. Okay, Let me see. Yeah, all the errors are gone. So that is our file viewer component. We still need to do lots of things in order to see it. But I hope you understood the most difficult part here, which is the render tree recursive function. And well, nothing special here in the preview. We're just rendering this render function with a file viewer data and how we use the selectors here. Okay, so that's, that's basically it. That's how he uses electricity. Just use u-sub selector and passes lecture and that's it. You get the data as simple as that. And hearing the unselect node, we dispatch the open file with an ODE. Okay, so I hope you liked this video. See you in the next lecture. Bye bye. 43. Added Custom Editor: Hi and welcome back. So now we're going to make the editor, make the component for the editor. So the editor is going to be this part here, okay, that part where we basically write the code. So that's going to be the interim. So for that, we're going to use the Monaco editor, which is a basically a package. I think it's backed by Microsoft. And it's like the open source version of VS code. Okay, so we simply say npm install Monaco editor came. And yeah, I think we also need to other dependencies which are Monaco Editor, react, and also are going to use a package from Lovasz. So let's install Monica, head indoors, last. React and also love it. Okay, In the meantime, let's go and create a new folder called Kusto painter. And here I'm going to create a new file called custom editor that TSX. And let's use our snippet to create this boilerplate code. Okay, again, I'm going to import lot of things so we don't have to do it throughout the video. So from React, we're going to use the user state hook. And they use called back from lunch. We're going to use that debouncing method. And we're also going to get the heavy door from Monaco editor slash react. And also here we're having a problem with That's basically because we also need the types for Lovasz. They are separate package. So let's go here and npm install save-dev types slash dash. Okay, so this is going to install types lot ash as a dev dependency on because this is just for TypeScript. So let's see. Yeah, we have now type loaded on that, that air is gone. So what else are we going to do? Oh, yeah. We're going to make a supportive extension object. Well, I guess we're going to do it later. So let's import also from store books. Let's import US have this badge and use up to lecture. Okay, What else I'm going to import from store slashes, files, slash files. I'm going to get the update file code. And also what else? I'm going to get the user file, file from typed slash files. And also last but not least, the loading component from components slash slash loading as slash loading. Okay, so that was all of the things that we're going to import. Let's also create a type called custom editor prompts. Here we're just going to receive an active file and that identifies going to be of type user file. So props is going to be of type custom-made or props, right? Sorry. So we also need one thing here. And we're going to declare here. And actually I'm just going to copy and paste it here. So this is basically, let me show you subverted, disappointed extensions. Object is an object that has, that maps the extensions to the name of the programming language. So we basically need this because the editor accepts a prop called the language. And language can be one of those things. And according to that, it's going to have, well syntax highlighting depending on the programming language. Okay, so let's start printing the logic here. So first of all, from the prompts, I'm going to get, I'm going to get the active file. And remember this active power has an ID, it has an extension. And it has some code, which I'm going to rename too. Original code because we're going to declare another variable called code. So here I'm just going to say code and set code. And I'm going to use the US statehood with the original code. Okay, great. Now I'm going to get the dispatch from US. Have dispatch. And I'm going to get oh, yeah. Also the dark mode. The dark mode, I'm going to get with the US Up selector. So this one is pretty easy. I say state, and then I get to state that dark mode. Okay? And then I'm going to get cancer language. So I'm going to say supported extension of the extension. So this can either return one of these things here or it can return on the fine. In that case, if it returns undefined them. I don't think there will be any problem. If there is a problem. Well, probably we can default this to something. Okay, so we're going to see when we actually write the code for this. Okay, so here I'm just going to return editor, so the component. But here we need to pass lots of props to this. So first the width to be 100%, the height is going to be 100%. So it occupies all of the screen. Now we pass the language which is going to read a programming language. Note that this is, I think, yeah. So this can be a string or undefined. So we are we are correct here. We don't have to do anything else here. Then the theme, the theme, the theme is going to be depending. If dark mode is enabled, then we're going to say VS dark, otherwise VS. So if you read on the documentation, these are the two possible values. Yeah, here we have actually the theme for the Monaco available options are dark and light. So it's not as light is light. So let's fix that. Then we have the value property and that's going to be the string of the code. So I'm just going to put here code. Okay? So that code is going to be this variable code here. Perfect. Then we have these loading property. So we need to pass it because rendering these editor can take its time. So according to the documentation, we can pass this loading prop. And it says here the loading screen before the editor will be mounted and defaults to this string loading. And then we need the last property with which is the unchanged property. So here we need to create the change handler. Okay, so let's start doing that. So constant. So this is going to receive the new code, which we can call this to be an empty string. And we can set the code to the new code. Perfect, but we need to also. So first of all, let's put it like this. So, okay, this set code sets the code internally for these components, but we need this code to be updated also in the Redux store. So for that, well, we want to dispatch an action every time we change like a letter in the code. So that's why I imported forum, not the bounds callback. So this eval function, sorry. So let's read through here. This creates a balanced function that delays bucking the function until after weight milliseconds have elapsed. Since the last time that the bound function was invoked. The function comes with a cancel method to console delivering location and a flush method. Invoke them, provide an options object to indicate functions should be invoked on the leading and trailing edge of the way timeout. Okay, So basically this is how we use these debouncing function. So first of all, we're going to create the bounds. And we're going to use this use called back from reacting. And here I'm just going to call the pounds. And these debouncing is going to accept a function which is going to be called. Okay? So that's going to be the first argument and the second argument is going to be the wait time. So I'm just going to put 1 second. So 100 milliseconds means 1 second. So here I'm just going to dispatch this update file code with sorry, with the file ID and with new code. So let me just go here and make sure that I am. Yeah, so we pass a file ID and then NewCo. Okay. So yeah, this this callback attach the file ID which is a string, and the new code which is a string a. So everything is still very red here because US callback, actually, as you can see here in the description, will return a memorized version of the callback that only changes if one of the inputs has changed. Okay? So basically we need to pass an array of dependencies. And here I'm just going to put an empty array. Okay, so what we need to do next is simply say the pounds, say you need to pass the ID and the new code. Okay? And that's it. That's everything. We need to do. This the way you make at the function. Inside functional React components. You use the US coal bag. Is this the balance method? Obviously, there are other ways of making this the bounds you can make it from scratch. But I don't want to do that. That's a little bit complicated. That's why I imported it from this package called lada. So yeah, that's basically everything we need to do. Let me see what happens if I take this. Yeah, it's going to complain. So let's get that time here. Okay. So yeah, that's that's basically it. I hope you like this video. See you in the next lecture. Bye bye. 44. Added Custom Tab Panel Component: Hi and welcome back. So now that we have the custom editor that uses the Monaco editor. And we're going to create something which is going to be like the container of these custom editor. And we're going to name it custom tab panel or yeah, top panel, I think it's good name. So basically what we have here, for example, in VSCode, if I open another file. So we have here taps, right? So each step represents file. So the custom tab panel is going to basically make the decision of what to render. So it's going to basically have all of the files endorse and it's going to hide, for example, it's going to hide this one if we are in the editor active file. Okay, so that's the logic behind these custom tab panel. So let's create a custom tab panel. And let's start. Well, let us start by importing some things. For example, we are going for the style from maturely materials, lashes styles. Great. Then I'm going to import the user file, the user file type, user file types files. And also we're going to import that custom editor from custom enter slash, who's gay. So we're going to import only these three things. Then we're going to create the type system tab panel prompts, which is going to be simply a negative file. We're going to pass the active file. And then we're going to bet the editor file, which remember, it can be a string or it can be low. Okay? So inside the components, first, let's specify that the prompts are custom tab panel prompts. And let's deconstruct from the prompts. Let's get the active file. And let's get the editor Andy file. And from the active, I'm going to get the idea. Okay, great. So now let's create a sound component. So this is going to be the tab panel container, which is going to be styled div. And this is simply going to have a height of 101%. 100%. Okay, great. Now here we're going to render that custom tab panel container. And we're going to specify that this has a roll of tab panel. So this is not necessary, but it's, It's useful for accessibility thing. Sorry, accessibility reasons. The important part here is we're going to make this thing HE them, if the editor active file, and sorry, this should be interactive file ID. So let's rename this editor. Id is not equal to the active file, sorry, to the idea of the active file. Okay. So basically to these ID here. Okay, so that's it. And the children is going to be the crystal molecule editor or the custom editor. And to these editor we only need to pass the active file, so the entire class. So probably we are going to need instead of deconstruct here, I'm just going to make it like this file. Here. I'm just going to say active file, that ID. Okay, so I think that's better. So let's see what we did here. Okay, So we just created that custom tab panel. These div is going to be hidden if the editor antiviral ID is not equal to the active file IDs. We're going to hide this one. And this one, this one is not going to be hidden. But any other custom tab panel is going to be hidden if it's not the active filter, active file. Okay. It's basically so I hope you liked this video. See you in the next lecture. Bye bye. 45. Added Custom Tab Label Component: Hi and welcome back. Now we're going to create the component for the tab label. So the Tub label basically is this part here, so the title. Okay, so we need to put here the extension icon, the name of the file, and also these clothes icon. And when we click undisclosed, Hi, Can we need to call our clothes file func? So let's create a new folder called Custom Tab Label. And creating a file called Custom Tab Label, dark TSX. Okay. So again, we're going to import lots of things here. So first of all, let's import the style from material UI. Material styles reflect. Then we're going to import user file. User file from material UIs, sorry for him, types slash files. Let's import as well extension icon, the extension icon component. Let's import the clothes icon from material UI, icons, material slash close. And that's also important. Use up Dispatch, dispatch from stores slash hooks. And also let's import that close file from slash close file. Okay, let's put this here. Great. Let's create a type called Wisdom tab labeled probes. And here I'm just going to receive the active file, which is going to be of type user file. So let's say the prompts is of type custom tab labeled probes rate. And now here inside these components, I'm going to get dispatch. Dispatch. And I'm going to get from the props. I'm going to get the active file. From the active, I'm going to get the ID, the name, and the extension. Okay, great. So now we're going to create the UNCLOS handler. And this is going to receive an event. And this event where we have to find that type of event. And it turns out that this is a mouse, mouse events. So with this mouse event, we can event stop propagation. So this is just because if we click here, we're also clicking on this tab itself. Okay? And when we click on this tab itself, we want to do additional things, but that's not for this video. We're going to see that in the next video. So that's why we want to stop propagation here. So the actions on these parent container are not executed. Then we just need to dispatch the close filed funk with the ID of the file. Okay, As simple as that. Now let's create a container and we're going to call these custom tab labeled container. And this is going to be a styled div. And simply I'm going to say this, lags, align items to the center. Let's justify content to the center. And that's text transform equal to none. Okay? So basically what we're doing here is that everything that goes inside these custom tab label is going to be horizontal. That's why display flex means and align items is going to line the icon and the text. And the extension I come to the center and justify content is going to put everything into center and the text transform none. That's only because when we use yeah, when we use this custom tab label inside the container, the container that we haven't seen yet. It I think it capitalizes everything. So that's why I'm setting this textbook formula. We're going to see this later. Don't worry about that. Then let's use these instead of deep. Okay? And here the first thing that we're going to put the extension icon, and we're going to pass the extension of the file. Okay? The second thing that we're going to put here is the file name. And the file name is going to be another component. So filename is going to be styled there. And this time I'm going to get the theme. And I'm going to return an object with batting pixels top and bottom and five pixels to left and right. And the color is going to be thin that font, because we want to make sure these text color changes based on the dark mode. So simply what we're going to do here is saying, Sorry, I'm having trouble. Okay. File name and the name of the file. And that's it. Okay. And the last thing is going to be the closed cycle. So close I can, okay, and we're going to put some styles here with the ESX property. So the position of this thing is going to be absolute, right? To be 0. We want the color, again to be based on the color of the font. And we also need the onClick. So the onclick handler here is just going to be the UNCLOS hungry. Okay, So I think let's see, no overload matches this goal. So let's see. Okay, so basically the reason for this is because we didn't have the correct mouse event here. Mass event is an event that occurred to the user interacting with a point in the base such as a mouse. Common events he is in his interphase includes click, double-click mouse happen now some. But actually we need to import a mouse event from React, react important emails. So let's see if there's any difference and a description. Well now we don't have a description. Anyway, that was the cause of that error here. Okay, so that's it for this video. I hope you like it. See you in the next lecture. Bye bye. 46. Added CodeEditorContainer Component: Hi and welcome back. So we are just one step away to finish in our code editor components. So now we're going to wire everything together. So let's create a code editor container, something like that. Okay, and here we're going to create a container that TSX. Let's create the boilerplate code. Well, again, we're going to need to import lots of things here. So first of all, I'm going to import from material, UI slash material. I'm going to get the app bar. I'm going to get the tabs, the tabs component. So all of those components are going to be used from QL UI materials, lashes, styles. I'm going to get the style. And let's get France store slash books. Let's get used up dispatch and use up selector. What else? We're going to get the editor active file from stores lashes, licenses, files is less files. Let's also get select active files from stores last lectures slash select Active Files. What else? Let's get goose DOM panel and also custom tab labeled. Okay, Start tab. Tab again. So that's everything that we're going to import here. Let's start by getting dispatch. Dispatch. Let's also get the active files with US obsolete. And then we simply as a selector which is select Active Files. Then let's get the editor, active file editor, active file ID. And that is going to be with use AMP selector. And this time I just found the state. And then I get it from state dot files, dot editor, active file ID. Okay? So first of all, we're going to check if there aren't any files and the active files. So if active files of length, if that is the case, then we're going to render an empty message just as we did with the file viewer. So if you remember, I did something similar here, empty message based on, Let's create an empty message style component. So it's going to be styled. And I'm going to get the theme like this. And I'm going to simply display flex. Going to get 100%. I'm going to get justify content center. Align items to the center, line. Center. And also color is going to be a theme that font. So it is our dark mode. Okay, by doing that, I'm just, I'm just going to render that empty method. And it's only going to select file. Okay, and we need to return obviously. Okay, So yeah, now we have that above that, let's create great aunt on tab click handler. And this is going to receive an event. And this event is going to be a change event. Okay? So let's make sure that this comes from React. Change event comes from React. Okay? And we are also going to get the tap position, which is going to be a number. Perfect. So first of all, I'm going to get the active file. Like this. I like the Files tab position. Okay? And then I'm going to check if active file, that ID is different from the editor active file. Then I'm just going to dispatch the editor active file. Thumb, sorry. The set an interactive file action with the active file that I did. So with these, I said the editor active quality to these new active file ID. Okay? And also what I'm going to do is to get this value. Here. I'm just And say if there is an editor active file ID, then I'm going to get active files array. And I'm going to find the index. The index where the active file, dot ID. Active file, sorry, active file. That ID is equal to the editor active pilot. Otherwise, return 0. Sorry, like that. Okay, so that's going to be the top value. Now inside this div. Well first let's, let's make another style component and that's going to be decodes editor container. Well, we already used the container world, so I'm running out of ideas here. Let's name it code editor container div. So here I'm just going to save 100% and overflow hidden. Okay? So here we're just going to replace this like this. And I'm going to render the app component from material UI. The position of this thing is going to be static and the color is going to be default. And here comes the interesting part. I'm going to use the tabs component game. So let's go here and insert for tabs material UI. So React tabs component. So as you can see, it's basically this thing here. Okay? So we pass this tab, and here we pass each of the tabs. So we need to make a map to render all of those steps. So first of all, the text, color is going to be primary. Indicator, color is going to be primary. And again, you can see in the documentation all of these what are all of these things? So if we go to get taps and see for example, yeah, indicator color, well, not much to say. The color of the indicator. We're going to see what the indicator is. For. Now let's put the text color and the indicator color primary. The variant is going to be scrollable. So scroll, scroll, scroll like that. So this basically means that if you have like many open files like this, you can have this scroll here. So that means a scrollable. What else? Yeah, When we also need to pass the value which is going to be which tab is active right now. So that's the tough value. And we need the onchange, which is that on tab click. So every time, okay, Now we're hiring another similar to what we have. I think that's because, yeah, this tangent receives something here and we don't pass where I'm passing anything. So let's pass an empty object like this and see if the error goes away. Okay, So the children of these tabs need to be tapped components. So for that, I'm going to iterate through the active files. So for each active file, I'm just going to return the tab where the key is going to be the active. In fact, let me just deconstruct this thing here. The file from the active farm gain the ID. Okay. So is going to be key ID and the label, this is the interesting part. No label is going to be our custom tab label. And we just pass the active file here, the whole IP file. Okay, so now we have these custom tab label. Now below these tabs, we're going to render the custom tab panels. So again, let's iterate through active piles or each activity file. I'm going to first of all deconstruct active file to get the ID. So we can pass that ideas to keep. And we return the custom tab panel, okay? And the key is going to be the ID. And you'd pass the active file, the whole empty file. And we also, if we remember, if we go to the here, we also need to pass the editor, active valid editor, active file. It is going to be editor or active follow Dean. And that's it. Let me see what is happening here. So it looks like I'm missing a parenthesis here like that. And yeah, so the errors are gone now. So we are done with this component, that code editor container. Now, the last step that we're going to make in the last video is going to be the code editor page itself. So hope you liked this video. See you in the next lecture. 47. Added CodeEditor Page Component: Hi and welcome back. So after finishing, these components are going to be able to see our results. So this is just a matter of a styling and putting everything together, especially the file viewer, the code editor container. And that's it. So let's create a couple of components which are basically going to be like just to wrappers. So here I'm just going to say code editor. I really didn't have a better name for this. So first of all, let's import styles or style. Style from a journal you eyes lash materials slash styles. So this is just going to be a div with the theme. We will return an object with these plate height, 100%, with 100% justified content to the center, line items to the center. And the background color is going to be themed background. So that's going to be aware of heart dark mode. So these code editor did, I didn't find a better name for it is just going to be here. Code editor. And inside here we need to render the file viewer and the editor container. So let's import them by a viewer. I'm also the editor, code editor, container code editor. Again and again, just some style components. So this is going to be the file you were container. Again, it's going to be styled div. And here we're just going to say display blank. Blanks, one. Hi, 100%. Align items to the center, justified content to the center. It's going to have a max width of 300 pixels and an overflow oto. A border right? One pixel dashed black. Again and one more, which is going to be the code editor container, container. So again, I don't have good names for this. So I'm just going to go editor container, div. We're going to kind of better name. Then. Let me know. Hiked 100% and that's it. Okay, so now let's render inside here the file viewer container. Or going to render the file viewer. And also we're going to render below this, the code editor container. And the children is going to be the code editor container. Okay, Great. So that's just a bunch of CSS that we have to write. You wanted, you can modify all of that CSS if you think that's how you find the better way to do this. So let's go and let's go to localhost 3000 to see the final, the final result. So let's sign in here. Okay, so now we are here and as you can see, well, I already have these folder. So let me just first test these dark mode so as you can see, it is working correctly. Now let's open the workspace. And here I have these code. You can upload whatever you want. So here I just have my things here. So let's open ES lint ignore. And looks like we need to make a change here because this doesn't show correctly. Okay, so right now our code eight or looks like this. And the reason is pretty simple. These active files that map where we render the custom tab panels. This you'll be below the app bar. Okay, So this should fix it. Okay, let's see our warnings here. Okay. React whole callback, just, this is just a warning. Okay? So here we have our acoustic VS Code. Copy clone, whatever you want to call it. So let's say we have all of these things here. So for example, red means we don't have like markdown in R, so Bertha extensions. But this still can be opened, right? You're in luck. The same thing. And as you can see, this is working as expected. Let's see index.js. Yeah, everything looks correct to me. Let's try dark mode here. Okay. Yeah. So everything looks good to me. So that's it. That's all of our app. I hope you like how the result of the thing is. I suggest you to also look at everything that is being dispatched here. Redux store. So as you can see, for example, if I open a file by open to files, then I dispatch these inactive files and edit your file and those kind of things. So I suggest you to start playing with these and also try you want to improve something that you thought it was not good. Let me know in the comments. And yeah, this is basically it. Hope you like this video. See you in the next lecture. Bye bye. 48. Conclusion: Hi and welcome back. So we have finished with the course. We have created these awesome code editor and it works perfectly. So what is the completion of these curves? Well, we learned react with TypeScript, react best practices, redox, redox toolkit, material UI, testing, authentication with officers, protecting routes with the react router dom and 0, implement in dark mode and many, many other things. I hoped you enjoyed this course and see you in my next course. Bye bye.