React Crash Course: Building React App using Hooks, Mobx, Typescript and much more
Tags: react, tutorial, typescript, javascript
Published: 2020-01-13 22:24:07

---
canonical_url: https://ogzhanolguncu.com/blog/react-crash-course-building-react-app-using-hooks-mobx-typescript-and-much-more
title: 'React Crash Course: Building React App using Hooks, Mobx, Typescript and much more'
---
<h1>Introduction</h1>

Today we will be building Note taking app using React. It will not be as fancy as you may think, but it will the do job. Before we delve further into react let's see our apps final look.
<hr/>
<img src="https://thepracticaldev.s3.amazonaws.com/i/on1x5b2p4txmubzkk0rz.PNG" alt="apps-final-look"></img>
<hr/>
<h2>Project Structure</h2>
First of we will start using this command to create react-typescript app <code>npx create-react-app noteTaking --template typescript</code>
At this point, you should have something similar to that<hr/>
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/4ipiz7qpki7ydgndofrn.PNG)<hr/>
For this course you may delete App.test.tsx, logo.svg, setupTests.ts. After you made the necessary adjustments go into your  <strong>App.tsx</strong> file and follow the steps.
<hr/>
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/q1iehar25914zy9txxas.PNG)
<hr/>
You may also delete <code>index.css</code>, and then remove it from <code>index.tsx</code>. If you structured your project like I did you should've something identical to image below.
<hr/>
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/1pnnqskxwvs4ihsxgz1k.PNG)
<hr/>
Let's see if our app works. Simply type <code>Yarn start</code> or <code>npm start</code>. Open your favorite browser and type __localhost:3000__. If you are seeing __Hello world!__ congratulations you successfully structured your app.
<h2>Features</h2>
We will split our app into features. Each feature is a part of your app like home, nav, footer. In our case we've got only one feature and it's note. But our note's have its own quirks such as dashboard and form. Let's get our hands dirty.

Before going any further let's install <a href="https://react.semantic-ui.com/">Semantic UI React </a><code>yarn add semantic-ui-react</code>. Semantic UI going to buy us so much time since we don't have to write our boilerplate components by hand. After you successfully installed semantic add this CDN into your __index.html__ in __public__ folder <code>//cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css</code>. Now your project should look like this.
<hr/>
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/7dqkv4v0mrbllgs3njkx.PNG)
<hr/>
##Our First Component
First off we start building the __NotesDashboard__ component. That component will be a box for other components. We placed everything inside this component and then we'll slowly break things into tinier components.
<hr/>
{% gist https://gist.github.com/ogzhanolguncu/2d9b48db5f571e7039c041bc05857b69 %}<hr/>If you are too lazy to type you can go ahead and copy it from Semantic UI's page but I advise not to, just bear with me and type. By the way, before we proceed I would like to talk about __Fragment__ component. This component acts as an empty div so instead of using empty divs we are using __Fragment__. It also renders faster.
### Let's break things apart.
We will make two component one for __note lists__ and another one for __note form__ and call them inside our __NotesDashboard.tsx__.<hr/>{% gist https://gist.github.com/ogzhanolguncu/359f3b4304d0714e27d26ab49955bd0b %}
{% gist https://gist.github.com/ogzhanolguncu/53d51766fdccc5e88d42c75ace39e293 %}
{% gist https://gist.github.com/ogzhanolguncu/0b90610a69166e7d843296b6ce4bf7a1 %}
<hr/>
Before we check how our app looks we should add __NotesDashboard.tsx__ to __App.tsx__<hr/>![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/dzxqy872pv0ku45ncgy0.PNG)<hr/>Let's see how our app looks like now. <hr/>![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/iyg6bb4dtblf9p1e3opx.PNG)<hr/>

## Our First Model
Since we are using typescript we need models to map API calls, benefit from tslint, giving appropriate types to our functional components. So let's get started. First, we are creating a file named __note.ts__ and placing it under the models' folder.
<hr/>![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/xa8p9wlinv694n5car78.PNG)
And start defining our model.
{% gist https://gist.github.com/ogzhanolguncu/a127357b80313db0393afc4292145d1e %}
We should give valid types to our properties such as string, number, boolean and even define arrays like this string[], number[]. For this particular tutorial, we only need one model.
##API Agent
![Alt Text](https://www.serbia.com/wp-content/uploads/2013/01/007_james_bond__skyfall_movie_poster_by_teamkill3r-d5l0lwc.jpg)

All jokes aside our __agent.ts__ file will communicate with our backend
and map the returned or sent values into previously written __notes.ts__ model. 
For that, we create a file named agent.ts inside api folder. 
<hr/>
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/08w05ydm083zzddt7283.PNG)
<hr/>
Before going any further we should install <a href="https://github.com/axios/axios">Axios</a>. Type __<code>npm install Axios</code>__ or yarn add axios to your console. __Axios__ will make our lives much easier, it simplifies API calls and you don't have to deal with fetch anymore since it's not as intuitive as Axios.
{% gist https://gist.github.com/ogzhanolguncu/dc72ca9ed6525427b7aa3e0c8e3809c0 %}
<hr/>
__Line 4__: We are defining our base url. I've used <a href="http://mockapi.io/">__mockapi__</a> in this tutorial to simplify backend process to narrow our focus specifically to frontend.

__Line 5__: Since we are only interested in responses body we creating arrow function that takes __AxiosResponse__ as a parameter then return response data as a result, in this case, __response.data__.

__Line 8 to 25__: We are creating a request object consist of __GET__, __POST__, __PUT__ and __DELETE__, all requests require a URL and body beside __GET__ and __DELETE__. __Axios__ first takes request type and then returns a promise( Promises are a function that can be chained one after another. If your first function finishes then next function in your execution chain starts. See this link for further information [Promise](https://developer.mozilla.org/tr/docs/Web/JavaScript/Reference/Global_Objects/Promise) which takes a __responseBody__ function as a parameter in our case.

__Line 28 to 34__: Creating API calls specifically for __Notes__. As you can see __CREATE__and __UPDATE__ requires an __INote__ model as a parameter. Others take either take id or none. And we've used [Template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) which can be used as a placeholder for your variables using __$__ sign.

##Stores, observables and actions
If you are familiar with state management term you probably already know but let me briefly explain what it is. State management is a __Single source of truth__ so your data must come from only one place. What this brings to the table is that data manipulation becomes dead simple since we already knew where and how all the data is stored. Let's dive in.

First, we should install [MobX](https://mobx.js.org/README.html) using __npm install mobx --save__ command and then create __noteStore.ts__ inside store folder.
<hr/>
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/q35p4omkzdm7f4pwajis.PNG)
<hr/>
.And we should enable experimentalDecorators for decorators. So your __tsconfig.json__ should look like this.
{% gist https://gist.github.com/ogzhanolguncu/6a8cddff8df7d5865d961accf1d65e3b %}

Now we can start typing our __noteStore.ts__. Like before I'll put everything at once then explain each one by one.

{% gist https://gist.github.com/ogzhanolguncu/99d7db78c17b8dac3891a53ca00b7a0c %}

__Line 7__: We define an observable map([An Observable emits items or sends notifications to its observers by calling the observers' methods.](http://reactivex.io/documentation/observable.html)) which stores any variable as a key-value pair and by convention we call it registry. 

__Line 8__: And note to track our note.

__Line 9__: We track __Submitting__ because whenever we submit we should be able to show users that we are submitting their data into our database and we do this by adding loading indicator to submit button. This submitting thingy will clarify in later in this tutorial.

__Line 10__: Same reason as submitting to show our users we're loading the data.

__Line 11__: We should be able to track the data we want to update.

__Line 13 to 15__: Getting data from our registry means we don't have to go to the database if we already have the data. And you can either set or get to the registry.

__Line 18 to 20__: If you want to do some custom logic over your data @computed decorator is your best friend. In this block of code, we cast our registry values into an __array__ so we can iterate it over by using __javascript map__.

__Line 22 to 26__: First we set __selectedItemId__ observable which it's value comes from parameter and then we call __getNotesFromStore__ to fetch single note from our registry finally we return __toJs__ which converts an (observable) object to a javascript structure.

__Line 29 to 50__: We define our @Action(MobX insist on using __actions__ when altering the state of action)and are going to use [Async - Await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) function. I'm not gonna go into detail of this if you wanna learn more simply read the docs. First, we check if we already have the data in our store if so we return __toJs(note)__. If we are going to fetch from an API we set __loadingInitial true __ and let our users see a loading indicator and then invoke our agent to fetch from API then use __runInAction__(MobX tell us if we are going to change the state of observable in an async function we should always use runInAction). After receiving the data, set the __note__ and __registry__ observables and set __loadingInitial to false__ since data is now in the store we need to set it to false to get rid of loading indicator. We've used Try-Catch block because something may happen without our notice so want to handle this situation somehow.

__Line 53 to 68__: Actually we are pretty much doing the same thing at __Line 29 to 50__ except we are now defining a variable called note as __INote[]__ and let Axios know that we are expecting an array type of INote. Since we are fetching a list of data we iterate them over using foreach and set __noteRegistry__.

__Line 71 to 84__: Since we are submitting data against API we set __submitting__ true and calling agent to create a note. After this function successfully executed we set the new value to our registry.

__Line 87 to 101__: Almost the same as creating function but we set our new value to __note__ observable.

__Line 104 to 119__: Calling our agent and deleting note both from store and API.

## It's time to see our actions in an action
Before doing anything, we first __npm install mobx-react-lite__ and then do as shown below. 
{% gist https://gist.github.com/ogzhanolguncu/d02ca2365bb3c3d2b4327d56a2370169 %}

To retrieve the most recent value from the store, __useContext__ comes to our aid. __useContext__ takes our stores and makes destructuring available so we only get the actions we need. Then we use another hook called __useEffect__  what this hook does is, it takes our action and runs it then at __Line 15__ receives a dependency if any of these dependencies change it runs the function body again. If you are curious why we called __loadNotes__ here because of __NotesDashboard.tsx__ being our container for other components so before doing anything we need to initialize our notes array. Since any of the actions change our notes array __loadNotes__ will know and re-render the page.

{% gist https://gist.github.com/ogzhanolguncu/059b2ec0149b87603c4071cce629619c %}

One thing I should be mentioning about is __selectNote__ this prop will be used for editing a note in future. As previous, we've used __useContext__ to call our store, then we deconstructed the values. 

In order to iterate over the notes array we are going to use __map__ and one crucial thing to bear in mind is that whenever you __map__ over something,
always assign a key so can react differentiate each list. Since your key going to be something unique like __ID__ property, react can always tell apart. To access properties inside the map, we use __curly braces__. In curly braces, we can call whatever prop we want __id, title, description__.

At __Line 17 and 18__ we've used __onClick__ so if anyone clicks to the trash-bin icon, this will trigger our deleteNote function or if anyone clicks on an item in general, we store this in selectNote and send it to form so the user can easily reshape the stored data.

Before we move on let's install so packages type __npm install --save final-form react-final-form__ and __npm install --save revalidate__ and for react types we also need some complementary packages __npm install @types/revalidate__. React final forms will do the heavy work for us and we're going to combine it with revalidate to validate our forms against users. 

###Forms
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/j6so54b5zi20umag0awo.PNG)
<hr/>
Create __TextInput.tsx__ and __TextAreaInput.tsx__as shown in the image inside __common/form__ folder. These components will be generic, so it can be used in any application you are going to write in the future. Let start off with __TextInput.tsx__.

{% gist https://gist.github.com/ogzhanolguncu/aff34b2fddd855611e1a9f6b979352d7 %}

We start with an interface called IProps which inherits __FieldRenderProps__ and FormFieldProps. Since we are using functional components, we can use our IProps interface as a type and deconstruct its values as we did before. If the form field touched or validation does not meet with conditions, it will show the validation errors. Also, we used spread operator { ...xyz} to spread out the input props to our input field.

{% gist https://gist.github.com/ogzhanolguncu/18fbd42060e6a30b0fd6a1835e8821ff %}

Almost the same as __TextInput.tsx__ but the only difference is that we used __<textarea>__ instead.


### NotesForm with Final-form
{% gist https://gist.github.com/ogzhanolguncu/619ecb005c1c71c1a993587d98cc36d7 %}

In addition to previously seen hooks such as useContext and useEffect, we now also have useState which basically takes a prop and prop setter. We'll use this state to initialize our form when updating.

At __Line 18 to 21__: Our useEffect will run if any of its dependencies change in our case __selectedItemId and selectNote__.

At __Line 24 to 28__: We use combineValidator from __'revalidate'__ package. First, we set the condition then the message. isRequired is not the only condition, there are also isAlphanumeric, isNan, isArray and much more. By the way, the property of validate comes from __name__ attribute of an input field.

At __Line 31 to 38__: Function receives our form input as a parameter then if __values__ has id, it treats it as an edit otherwise calls  __createNote__.

At __Line 50 to 76__: Final form takes validate, initialValue, onSubmit, render props. Validate uses our combineValidator defined at __Line 24__, initialValue uses __note prop__ only if any item clicked for editing defined at __Line 16__ and render. Render has its own props to handling the submit and check the form states such as pristine, dirty, touched etc.

__Line 55 to 62__: To reset the form after submit, we checked if handler returned any promise if so we reset the form otherwise return the promise back.

__Line 63 to 67__: We used __Field__ from react-final-form. Field receives component prop which we created earlier as __TextInput.tsx__.

__Line 68 to 72__: This time __Field__ receives component prop which we created earlier as __TextAreaInput.tsx__.

__Line 73__: If we are submitting we disabling the button and showing loading indicator.

Before finishing up, one last thing to do. If we are loading or submitting from now on users will see loading spinner.

{% gist https://gist.github.com/ogzhanolguncu/8520ffb2892c28a564632fe74923a63e %}

Finally, we completed our app. If you encounter any problem you can always check the repo <a href="https://github.com/ogzhanolguncu/React-Mobx-Typescript-CRUD">Code</a>.


Thanks for reading.