IMPORTANT:
Some of the content here is a personal summary/abbreviation of contents on the tutorial at https://fullstackopen.com/en/part0. It seems to also teaches a bit on Node.js and GraphQL, both of which I think are useful.
Feel free to refer to the official site if you think some of the sections written here are not clear.
Intro
This course will use Node.js and Express to create web servers. First let us recap a bit of javascript.
Some sample code covered in this section include some .js
dynamically adding contents:
1 | var xhttp = new XMLHttpRequest() |
basically this is related to Event Handlers:
- an event handler for event
onreadystatechange
is defined for thexhttp
object doing the request. When the state of the object changes, the ==browser calls the event handler function.==
The mechanism of invoking event handlers is very common in JavaScript. ==Event handler functions are called callback functions==. Because those functions are called by the browser at an appropriate time.
DOM
The functioning of the browser basically takes the html and understands it as a tree:
1 | html |
where the same tree structure is also reflected in the console in the Elements tab.
Therefore:
DOM
Document Object Model, or DOM, is an Application Programming Interface (==API==) which enables programmatic ==modification of the element trees== corresponding to web-pages.
example include the piece of code used above:
1
2
3
4
5
6
7
8 var ul = document.createElement('ul')
data.forEach(function(note) {
var li = document.createElement('li')
ul.appendChild(li)
li.appendChild(document.createTextNode(note.content))
})==topmost== node of the DOM tree of an HTML document is called the
document
object. Basically it looks like:![]()
Forms and POST
This is a recap of how forms works and how a node.js
backend deals with it.
First on the webpage:
where notice that
action='/new_note'
means once submit is hit, it sends to/new_note
as URL- it uses
method="POST"
Then, the server does two things:
1 | app.post('/new_note', (req, res) => { |
- it adds the data
req.body.note
- it send a response of ==redirect== to the homepage (i.e. refreshes the page) by
res.redirect
- otherwise, you cannot see the changes
Lastly, on your browser, you will correspondingly see
where:
- the status code is
302
which is ==redirect== - the redirect location is
/notes
After this response, the browser redirects/refreshes the page and updates can be seen
Single Page APP
In recent years, the Single-page application (SPA) style of creating web-applications has emerged. SPA-style websites don’t fetch all of their pages separately from the server like our sample application does, but instead comprise only ==one HTML page== fetched from the server, the contents of which are ==manipulated== with JavaScript that ==executes in the browser==.
- in other words, all changes are as if they happened locally on the same page, meaning that you don’t need to “redirect/refresh” to display changes of the content
A single page app version of our example application can be found at https://studies.cs.helsinki.fi/exampleapp/spa.
The key changes we see are the actions when we submit changes:
notice that the form has ==no action or method attributes== to define how and where to send the input data.
What happens is that the code:
1 | var form = document.getElementById('notes_form') |
where we register an event handler to handle the form submit event.
The event handler immediately calls the method
e.preventDefault()
to prevent the default handling of form submit. The default method would send the data to the server and cause a new GET request, which we don’t want to happen.- note: the default behavior for W3 standard is to ==reload/request the same URL if no form action is supplied==.
then, it updates the
note
variable and redraw the data usingredrawNotes()
, all of which would have happened locally in the browser
Intro to React
The code we have written before all involved vanilla JavaScript. More often we will be using some JS library to speed up development, and one common combo recently is React + Redux, which we will cover in this tutorial.
First, lets begin by creating a REACT app
1 | $ npx create-react-app part1 |
where if you are on windows, try to:
- use
cmd
instead ofpowershell
, the latter somehow is bugged when I test it - make sure that
create-react-app
is installed bynpm install -g create-react-app
Then, you can start your app by:
1 | $ cd part1 |
The code of the application resides in the src
folder.
Note
If this is your first time, and you are using VSCode, then you might want to make sure you have changed the code reformatting to
JS React
instead of pureJS
Component
The simplest structure of a React project looks like
1 | src/ |
If you look at index.js
, the last line says:
1 | import App from './App' |
where:
- The ==file==
App.js
now defines ==a React component== with the nameApp
. Then contents ofApp
defined inApp.js
into the div-element of filepublic/index.html
, having the id value ‘root’.
Then, the App
variable (which defines a function) in the App.js
can look like
1 | import React from 'react' |
where basically the ==return value of App
== will be rendered.
- Any JavaScript code within the curly braces is evaluated and the result of this evaluation is embedded
JSX
It seems like React components are returning HTML markup. However, this is not the case. The layout of React components is mostly written ==using JSX.== Although JSX looks like HTML, we are actually dealing with a way to write JavaScript. ==Under the hood, JSX returned by React components is compiled into JavaScript.==
1 | const App = () => { |
this is equivalent of what we had above, but under the hood ==the compiling is handled by Babel.== Projects created with create-react-app are configured to compile automatically.
- in practice, everyone prefers writing JSX, as it is simple and effective (analogy with template engines like Thymeleaf)
Multiple Components
Variables as components are good because they can be reused easily.
- if you are using them across
.js
files, do not forget to export them at the end of the file
For instance, you can render multiple instances of the Hello
component:
1 | import React from 'react' |
note:
a ==requirement== for React component is that their names must be capitalized (otherwise they will not be rendered)
Another strong ==convention== is the idea of a root component called
App
at the ==top== of the component tree of the application. Nevertheless, as we will learn in part 6, there are situations where the component App is not exactly the root, but is wrapped within an appropriate utility component.
Props: Passing data to components
Data can be passed as ==properties of an object== across components. For instance:
1 | const App = () => { |
Then, you can receive it in Hello
component by:
1 | const Hello = (props) => { return ( |
where notice that we are accessing the name
property.
Note that if you want to pass ==variables==, you need to ==evaluate them== before passing:
1 | const Hello = (props) => { |
notice that we are doing <Hello name={name} age={age} />
.
Some Notes
A React ==component== (usually) needs to ==contain one root element.==
This means that the following will give an error:
1 | const App = () => { |
because there is no root element surrounding the inside. However, if you certainly want to avoid the extra <div>
tag, you can also do:
1 | const App = () => { |
where we used fragments, i.e. by wrapping the elements to be returned by the component with an empty element <>