React Quickstart Tutorial
Contents
- Inspiration
- Prerequisites
- Setup
- The React Component
- Events
- State
- Hooks
- Routing
- Extra Bits
- Sample Network Request and Render
Inspiration
I like using React, building reuseable blocks of code ( Components ) in your own style is quite a fun and stimulating experience. You may meet several react persons who use the framework but their code can be drastically different ( which can also be a very bad thing ), but I like to find my own way of doing things and react allows that.
Prerequisites
To start you'll need Node, npm and preferably npx, you can skip to the next section if you already have these installed ( next section )
Installing Node
OPTION A: (Recommended NVM ( Node Version Manager)
It's generally recommended that you use nvm to install and manage versions of node. You can see instructions on how to install for you OS here. Definitely use the above link if you can, however if not you can try running these...
install via curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
reload your terminal
source ~/.bashrc
check the install
nvm -v
use nvm to install a version of node ( e.g. 16 )
nvm install 16
OR
use nvm to install the latest version of node
nvm install node
use nvm to use a version of Node it installed ( e.g. 16 )
nvm use 16
OPTION B: Direct Install
You can visit here for installation instructions for your specific OS.
npm and npx
npm and npx are usually installed alongside node, you can test with npm --version
and npx --version
.
Note: Node, npm and npx are all different things, Node is the execution environment ( basically the thing that runs the code ); npm, Node Package Manager, manages packages for node; npx, Node Package Execute, allows us to run installed node packages. The versions of each of these things are (mostly) independent and therefore when you run npm --version
or node --version
or npx --version
DON'T EXPECT to see the same number.
Depending on which option you chose npx may not be installed, as such you can run the following:
install npx globally ( DO NOT RUN IF YOU ALREADY HAVE npx INSTALLED, again check with npx --version
)
npm install -g npx
Setup
Files and Core Dependencies
Let's create a folder react_app
, and inside react_app
create a src
folder and a public
folder, inside public
create an index.html
file and inside src
create an index.js
file.
Edit index.html
and index.js
to reflect the following:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>React Tutorial App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
index.js
console.log('Hello I\'m working');
Now let's initialize our package management
npm init -y
Now let's install our core dependencies
npm install --save react react-dom
Your structure should look something like
react_app
|- /node_modules
|- ...
|- package.json
|- /public
|- index.html
|- /src
|- index.js
React Scripts
react-scripts
is a tool we will use to run and build our react code. The browser doesn't actually understand react, we can use react-scripts
to create a development server which would transpile and serve our code in the browser while constantly watching for changes we make and reloading those bits. We will also use react-scripts
to build a bundled app that we can deploy, for now let's install
npm install --save-dev react-scripts
Now for react scripts to work, it needs at minimum, a specific structure and some specifications in our package.json
. For the structure it expects a public
folder with an index.html
file and a src
folder with an index.js
. As for the specifications, we have to say which browser(s) we're going to use to develop and build to support. We will add these specifications after the devDependencies section in our package.json
,"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
The development subsection is fairly obvious, however you can read about the browserslist production values here.
Your package.json should look something like this ( exact values WILL DIFFER DO NOT COPY )
{
"name": "react_app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"react-scripts": "^5.0.1"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Now let's start our development server, navigate to the react_app
folder and run
npx react-scripts start
Your browser should open to localhost:3000, with index.html loaded and index.js injected for us, so if you open the console you'll see our log 'Hello I\'m working'.
Note: There is a tool create-react-app
that could have been used to automatically create our initial structure however when I first started out it felt a bit overwhelming and often conflated my understanding of things operated. When learning it feels much better to take things one step at a time rather than having to decipher a bunch of boilerplate code.
The React Component
JSX
What is JSX ? Well it stands for Javascript XML but we can basically think of it as Javascript in HTML... in Javascript. As a dumb example, think about how you would put some stored text input text_variable
in a <div>
tag.
Normally you would do something like add an id to the tag <div id='some_reference'>
then grab the element using document.getElementById('some_reference')
and then do something like set it's innerHTML to text_variable
.
With JSX if we want to put text_variable
in a <div>
, we just put it
<div>{text_variable}</div>
With JSX we can put any Javascript Expression directly into HTML by putting it into curly braces. ( Javascript Expression = any javascript code that resolves to some value ). How does this concept of Javascript Expressions in HTML helps us ? Well now we can use html almost as a template whose contents are created by our logic and data, this is the basis of a component.
What is a Component
Components are the building blocks of react, a component can be conceptualized as a custom element that you create. This 'custom element' or component usually structured as accepting some data input and returning some JSX ( recall JSX allows us to build a template whose contents we manipulate via javascript ).
As a quick example here's a CalculatorComponent
that accepts two parameters; two numbers num_1
, num_2
and then returns JSX that displays the sum.
const CalculatorComponent = (params) => {
const { num_1, num_2 } = params; // we are pulling out the two arguments we passed in num_1 and num_2, the name params is not important and can be changed
return (<div>
{num_1 + num_2}
</div>)
}
Now we can use our component almost like any other element like <CalculatorComponent/>
we can pass in our values similar to how normal attributes are passed in to html elements like <CalculatorComponent num_1={3} num_2={4} />
. Now that we have some idea about components let's actually put it into action.
Rendering React
Let's finally render our first component, to do that we'll need to use the core react libraries react
and react-dom
. To render react we need to (1) find a place on the DOM where we want to render our component(s) (2) actually load our component into that place. Let's do it using our CalculatorComponent
edit your index.js
to reflect the following:
import React from 'react';
import { createRoot } from 'react-dom/client';
console.log('Hello I\'m working');
const CalculatorComponent = (params) => {
const { num_1, num_2 } = params; // we are pulling out the two arguments we passed in num_1 and num_2, the name params is not important and can be changed
return (<div>
{num_1 + num_2}
</div>)
}
const root_element = document.getElementById('root');
const react_root = createRoot(root_element);
react_root.render(<CalculatorComponent num_1={3} num_2={4} />);
Once you have saved you should see a '7' appear on your browser, congratulations you've created your first react app. let's talk a bit about what's going on, first our imports; without getting into the mess of things React from 'react'
is used to construct our Component and { createRoot } from 'react-dom/client'
is used to load our component onto the page. We then define our component CalculatorComponent
using the code from before, grab the empty div
identified by root
( see index.html
), create the root or base of our react application then finally render our component using the created root/base.
App Structure
This was a very simple example using one file, however it's not very realistic, let's see how we can split our code across multiple files using some established conventions ( this in most cases is how you should structure and load your app ).
First let's seperate our CalculatorComponent in it's own file Calculator.js
inside our src
folder and make some minor modifications
import React from 'react';
export const Calculator = (params) => { // no need for the word 'Component' to be attached, it's already understood
const { num_1, num_2 } = params; // we are pulling out the two arguments we passed in num_1 and num_2, the name params is not important and can be changed
return (<div>
{num_1 + num_2}
</div>)
}
Now let's create a component that will be used as the root of our application where we will load all other React components, we'll call the component App
, create a new file App.js
inside src
and add the foll:
import React from 'react';
import { Calculator } from './Calculator';
export const App = () => {
return (<div>
<Calculator num_1={3} num_2={4} />
</div>)
}
Explanation: Our App
component imports our Calculator
component from Calculator.js
and uses it with num_1
as 3 and num_2
as 4
Finally let's modify our index.js
to render our root/base component App
import React from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './App';
console.log('Hello I\'m working');
const root_element = document.getElementById('root');
const react_root = createRoot(root_element);
react_root.render(<App/>);
Your file structure should look like the foll:
react_app
|- /node_modules
|- ...
|- package.json
|- /public
|- index.html
|- /src
|- index.js
|- App.js
|- Calculator.js
Once saved you should see the result rendered on your page.
Events
DOM and VDOM
The DOM is a representation of an HTML document that facilitates it's manipulation. For example when we call document.getElementById
we retrieve a DOM node which we then use to apply changes to the document. Without going into too much depth, react
creates it's own version of the DOM called the virtual DOM ( or VDOM ). The VDOM is used to optimize rendering, i.e. instead of replacing the entire DOM, react compares the DOM and it's VDOM and only changes what's needed in the DOM to reflect new changes. This bit is a bit beyond this tutorial, you can read more about these concepts here and here.
Synthethic Events
Since when using react we don't use the DOM directly but a representation of it, we can't use native DOM events (e.g. onclick
) but rather synthethic events that react provides for us (e.g. onClick
). Secondly since we're using JSX i.e. using components to create HTML in our javascript code, when we pass functions to these events we pass the function itself rather than a string.
Traditionally it may have looked something like this
<button onclick='handleOnClick'>
Click
</button>
In react
using JSX we have
<button onClick={handleOnClick}>
Click
</button>
Again, note onclick
is the native DOM event which we replaced by react
's synthethic event onClick
, case being the only difference (lowercase vs cammel case), this is done by design to make things easy to remember yet distinct; and secondly instead of using a string of the function we pass in the function itself ( again JSX ).
State
useState
State, simplified, is variables. State within your app can be thought of then as, all the data currently loaded within your application. Let's zoom in a bit, to the state for a component i.e. the data / variables within the component. State can be thought of as the core react
, why ? Components update their content ( or react to ) the data within them. Therefore when working with data within a component i.e. when we create 'variables' or state, we have to do so in a way react can keep track of it. We create these 'variables' or state by calling useState
function.
When we call useState
there are 3 things to note; (1) a react
variable, (2) a function to update this react
variable, and (3) what the default value of this react
variable should be. Let's see a quick example of useState
, we will use it to keep track of a count
const [count, updateCount] = useState(0);
In the example, (1) count
is the special react
variable, (2) updateCount
is the function we use to update the value of count
, and 0
is count
's initial value.
REACTing to state
In order to fully appreciate how state works, we need to actually use it. let's create a component to count based on user inputs, we'll call it Counter
and create it in Calculator.js
.
Edit Calculator.js
to reflect the foll:
import React, { useState } from 'react';
export const Calculator = (params) => { // no need for the word 'Component' to be attached, it's already understood
const { num_1, num_2 } = params; // we are pulling out the two arguments we passed in num_1 and num_2, the name params is not important and can be changed
return (<div>
{num_1 + num_2}
</div>)
}
export const Counter = () => {
const [count, updateCount] = useState(0);// useState creates our variable 'count' and a function 'updateCount' to update our variable;
const handleCountBtnClick = (ev) => {
updateCount(count + 1); // a replacement for count = count + 1
}
return (<div>
Clicked {count} times.
<button onClick={handleCountBtnClick}> Click</button>
</div>)
}
Now all let's add Counter
to our App
component, edit App.js
to reflect the following:
import React from 'react';
import { Calculator, Counter } from './Calculator';
export const App = () => {
return (<div>
<Counter />
<Calculator num_1={3} num_2={3} />
</div>)
}
Your page should automatically refresh with our Counter
component loaded, now whenever you click the button, the count should increase.
Hooks
Hooks
Hooks are a bunch of functions that allows us to use react features easily. useState
is actually an example of a hook, as seen it allows us to create special react
state that our components use update it's content.
useEffect
useEffect
is the next most popular hook, it allows us to perform 'effects' between changes in specific states. useEffect
has two bits to take note of, (1) the functionality or 'effect' we want run, and (2) the pieces of state we want to run the 'effect' inbetween.
As an example, let us modify our Calculator
to take in two user inputs num_1
, num_2
and an operator operator
, our calculator will work such that if num_1
, num_2
or operator
changes we will attempt to recalculate the result live. To do this, of course we will use a useEffect
, the effect will be calculating a result, and the pieces of state we will be observing will be num_1
, num_2
and operator
because if any of these changes then we will need to recalculate the result.
import React, { useState, useEffect } from 'react';
export const Calculator = (params) => { // no need for the word 'Component' to be attached, it's already understood
const [num_1, updateNum1] = useState(0);
const [num_2, updateNum2] = useState(0);
const [result, updateResult] = useState('0')
const [operator, updateOperator] = useState('+');
const calculate = () => {
let updated_result = '';
if (operator == '+')
updated_result = num_1 + num_2;
else if (operator == '-')
updated_result = num_1 - num_2;
else if (operator == '/')
updated_result = num_1 / num_2;
else if (operator == '*')
updated_result = num_1 * num_2;
else
updated_result = 'Invalid Operator';
updateResult(updated_result);
}
useEffect(calculate, [num_1, num_2, operator]);
const handleOnChange = (ev, field) => {
const new_value = ev.target.value;
if (!new_value) // if input changed to nothing / null, then don't update anything
return;
if (field == 'num_1')
updateNum1(parseInt(new_value));
else if (field == 'num_2')
updateNum2(parseInt(new_value));
else
updateOperator(new_value)
}
return (<div>
<input type='number' defaultValue='0' onChange={ev => handleOnChange(ev, 'num_1')} />
<input type='character' defaultValue='+' onChange={ev => handleOnChange(ev, 'operator')} />
<input type='number' defaultValue='0' onChange={ev => handleOnChange(ev, 'num_2')} />
=
{result}
</div>)
}
export const Counter = () => {
const [count, updateCount] = useState(0);// useState creates our variable 'count' and a function 'updateCount' to update our variable;
const handleCountBtnClick = (ev) => {
updateCount(count + 1); // a replacement for count = count + 1
}
return (<div>
Clicked {count} times.
<button onClick={handleCountBtnClick}> Click</button>
</div>)
}
Let's take a minute to dissect what's here, in order;
First we used useState
4 times to create 4 pieces of state, functions to update them, and gave them default values.
const [num_1, updateNum1] = useState(0);
const [num_2, updateNum2] = useState(0);
const [result, updateResult] = useState('0')
const [operator, updateOperator] = useState('+');
Then we created a calculate function, which uses num_1
, num_2
and operator
to calculate and update result
.
const calculate = () => {
let updated_result = '';
if (operator == '+')
updated_result = num_1 + num_2;
else if (operator == '-')
updated_result = num_1 - num_2;
else if (operator == '/')
updated_result = num_1 / num_2;
else if (operator == '*')
updated_result = num_1 * num_2;
else
updated_result = 'Invalid Operator';
updateResult(updated_result);
}
We then used a useEffect
to say anytime num_1
, num_2
, or operator
changes run the calculate function, as shown useEffect
is a function call that accepts 2 things, (1) the functionality or 'effect' we want run in this case calculate
, and (2) the states we want to observe or rather states which affect our 'effect' in this case num_1
, num_2
, and operator
.
useEffect(calculate, [num_1, num_2, operator]);
The rest are things we've already gone over, handleOnChange
is a function we create to handle the changing of something, it accepts the actual change event ev
as well as some identifying keyword state_name
, it uses the event ev
to fetch the current entered and based on the keyword state_name
we update the relevant piece of state.
const handleOnChange = (ev, state_name) => {
const new_value = ev.target.value;
if (!new_value) // if input changed to nothing / null, then don't update anything
return;
if (state_name == 'num_1')
updateNum1(parseInt(new_value));
else if (state_name == 'num_2')
updateNum2(parseInt(new_value));
else
updateOperator(new_value)
}
Finally we have the JSX where we define our inputs to call our handleOnChange
function by attaching it to react
's synthethic onChange
event, however we wrap this function call in an anonymous function so that we can pass a specific keyword for each input.
return (<div>
<input type='number' defaultValue='0' onChange={ev => handleOnChange(ev, 'num_1')} />
<input type='character' defaultValue='+' onChange={ev => handleOnChange(ev, 'operator')} />
<input type='number' defaultValue='0' onChange={ev => handleOnChange(ev, 'num_2')} />
=
{result}
</div>)
Routing
Why Have Routes ?
Modern frontend frameworks operate on the basis that the entire app operates on a single page ( single page apps ). However, we still like the illusion of routing to different pages ( this can also be useful to the user since they often identify and navigate directly to a specific view by typing in the route ). It is entirely possible ( not recommended ) to build your own routing system however there's also react-router-dom
which is the defacto routing solution used for react
.
Basic React Router
react-router-dom
is a library that provides routing for react
. To get started lets install react-router-dom
run
npm install react-router-dom
To get started we need to the root of our application in a Component from react-router-dom
called BrowserRouter
, let's modify our index.js
to reflect the foll:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { App } from './App';
console.log('Hello I\'m working');
const root_element = document.getElementById('root');
const react_root = createRoot(root_element);
react_root.render(<BrowserRouter>
<App />
</BrowserRouter>);
Now let's modify App
to have two routes, /counter
for our Counter
and /calculator
for Calculator
, to do this we'll need to use the Routes
and Route
components from react-router-dom
. Routes
is where we initialize the routes for our application, it will contain all the Route
components for our app. Each Route
component is simply a path e.g. /calculator
and what to render e.g. <Calculator/>
let's edit App.js
to see these in action :
import React from 'react';
import { Route, Routes } from 'react-router-dom';
import { Calculator, Counter } from './Calculator';
export const App = () => {
return (<div>
<Routes>
<Route path='/counter' element={<Counter />} />
<Route path='/calculator' element={<Calculator />} />
</Routes>
</div>)
}
Now when you visit /counter
you'll see our Counter component and when you visit /calculator
you'll see our calculator component (easy right!).
Remember this is an illusion of different routes, we will not actually serve different pages; visting /calculator
loads the same page, the same code, but the Component specific to /calculator
; simply put BrowserRouter
must read the state of the browser and load the required Component / View. However there are many more things that BrowserRouter
does for us right out of the box, a quick example is keeping track of where the user has visited and facilitating backwards and forwards navigation between routes. Again remember these routes aren't real we are never leaving the page so there isn't anyting to go back or forward to. You can read more about react router here.
Routing Necessities
You'll very quickly notice, that the base of our application has nothing loaded i.e. if you go to localhost:3000
you'll see nothing, this is because we do not have a Route
for our base path /
, therefore nothing will load, there are a few options we will explore
OPTION 1: The most obvious let's just add Route and choose a component e.g. Calculator
,
import React from 'react';
import { Route, Routes } from 'react-router-dom';
import { Calculator, Counter } from './Calculator';
export const App = () => {
return (<div>
<Routes>
<Route path='/' element={<Calculator />} />
<Route path='/counter' element={<Counter />} />
<Route path='/calculator' element={<Calculator />} />
</Routes>
</div>)
}
This works fine, Components are meant to be reusable so no problems here, but a bit crude
OPTION 2: If we don't have something for a particular route e.g. /
we can redirect them to one, let's redirect /
to calculator
import React from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { Calculator, Counter } from './Calculator';
export const App = () => {
return (<div>
<Routes>
{/* <Route path='/' element={<Calculator />} /> */}
<Route path='/' element={<Navigate to='/calculator' replace={true} />} />
<Route path='/counter' element={<Counter />} />
<Route path='/calculator' element={<Calculator />} />
</Routes>
</div>)
}
Again works fine, demonstrates how to render a redirect such within BrowserRouter
so BrowserRouter
can keep track of where user has been.
OPTION 3: Create a new component that acts as a menu
In src
create a new file Menu.js
and add the following:
import React from 'react';
import { Link } from 'react-router-dom';
export const Menu = () => {
return (<div>
Most desolate menu in the world
<ul>
<li>
<Link to='/calculator'>Calculator ( ಠ ʖ̯ ಠ ) </Link>
</li>
<li>
<Link to='/counter'>Counter ◔_◔ </Link>
</li>
</ul>
</div>)
}
Now edit App.js
import React from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { Calculator, Counter } from './Calculator';
import { Menu } from './Menu';
export const App = () => {
return (<div>
<Routes>
{/* <Route path='/' element={<Calculator />} /> */}
{/* <Route path='/' element={<Navigate to='/calculator' replace={true} />} /> */}
<Route path='/' element={<Menu />} />
<Route path='/counter' element={<Counter />} />
<Route path='/calculator' element={<Calculator />} />
</Routes>
</div>)
}
Once you've saved, the base route will now render our very ugly menu Menu. React Router
has a lot more and very good documentation, please give it a read through if you ever find yourself amiss with routing.
Extra Bits
Conventions
A lot of the code I wrote was done to maximize readability however in practice there are some things that are common place.
Param Destructuring
This is how we access properties / parameters for a component, let's look back at the first version of <Calculator\>
, for reference
const CalculatorComponent = (params) => {
const { num_1, num_2 } = params; // we are pulling out the two arguments we passed in num_1 and num_2, the name params is not important and can be changed
...
}
We accepted an object we named 'params' and then proceeded to destructure and pull our num_1
and num_2
however in practice the norm is to destructure in the method signature / parameter list itself like so
const CalculatorComponent = ({num_1, num_2}) => { // we are expecting two properties to be passed, called exactly `num_1` and `num_2`, we can therefore pull them out immediately
...
}
useEffect
When we used the useEffect
we created a function calculate
to pass into the useEffect
reference
const calculate = () => {
let updated_result = '';
if (operator == '+')
updated_result = num_1 + num_2;
else if (operator == '-')
updated_result = num_1 - num_2;
else if (operator == '/')
updated_result = num_1 / num_2;
else if (operator == '*')
updated_result = num_1 * num_2;
else
updated_result = 'Invalid Operator';
updateResult(updated_result);
}
useEffect(calculate, [num_1, num_2, operator]);
However the 'effects' or functionality in useEffects
are usually only meant to be triggered in the useEffect
so people usually use an anonymous function or rather ES6's version, an unassigned arrow function, and write the functionality directly in the body
useEffect(()=>{
let updated_result = '';
if (operator == '+')
updated_result = num_1 + num_2;
else if (operator == '-')
updated_result = num_1 - num_2;
else if (operator == '/')
updated_result = num_1 / num_2;
else if (operator == '*')
updated_result = num_1 * num_2;
else
updated_result = 'Invalid Operator';
updateResult(updated_result);
}), [num_1, num_2, operator]);
As you can see the body of the functions are exactly the same, the only difference is we just wrote it directly in the useEffect
using an unassigned arrow function.
Sample Network Request and Render
As a quick example of how we can do network requests and render the results I'm going to fetch art pieces using The Art Institute of Chicago API.
Let's begin by installing axios to make making requests easier.
npm install --save axios
Now create an Art.js
in src
, we'll have two components Art
being the main component and ArtPiece
being an individual art piece. The code here will be a bit closer to how things would usually be done
import Axios from 'axios';
import React, { useRef, useState } from 'react';
export const Art = () => {
const [art_data, updateArtData] = useState([]);
const searchInput = useRef(null); // holds a reference to an element
const handleSearchArt = (ev) => {
const title = searchInput.current.value; // similar to title = document.getElementById('search-text-input').value;
const params = { q: title, limit: 5, fields: 'id,title,image_id,artist_display' }; // sample set of params, limits the number of results to 5, and only returns the id, title, image_id, and artist_display fields
Axios.request({
url: 'https://api.artic.edu/api/v1/artworks/search',
params
}).then(res => {
const { config, data } = res.data;
const updated_art_data = data.map(artPiece => ({ config, ...artPiece })); // add config to each art piece
updateArtData(updated_art_data);
}).catch(err => console.log(err));
}
return (<div>
<input ref={searchInput} id='search-text-input' type='text' />
<button onClick={handleSearchArt}> search </button>
{art_data.map(art_piece_data => (<ArtPiece key={art_piece_data.id} {...art_piece_data} />))}
{/* Don't be overwhelmed by {...art_piece_data} this is another example of destructuring, each key,value pair is passed down as if it were independent */}
</div>)
}
// Again we pull out each argument passed by name using destructuring
const ArtPiece = ({ config, title, image_id, id, artist_display }) => {
return (<div>
<img src={`${config.iiif_url}/${image_id}/full/843,/0/default.jpg`} />
<h3>{title}</h3>
<p>{artist_display}</p>
</div>)
}
useRef
is an example of a hook we can use to hold a reference to an element, in this case we used it to hold a reference to our search input element; The id
is left in for comparison.
Now we simply need to add a route to load Art
, edit App.js
import React from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { Art } from './Art';
import { Calculator, Counter } from './Calculator';
import { Menu } from './Menu';
export const App = () => {
return (<div>
<Routes>
{/* <Route path='/' element={<Calculator />} /> */}
{/* <Route path='/' element={<Navigate to='/calculator' replace={true} />} /> */}
<Route path='/' element={<Menu />} />
<Route path='/counter' element={<Counter />} />
<Route path='/calculator' element={<Calculator />} />
<Route path='/art' element={<Art />} />
</Routes>
</div>)
}
We can access our /art
and search for art pieces, feel free to add it to the great menu :P
Final Thoughts
There you have it, a basic yet somewhat comprehensive ( I hope ) guide on react, there are many more concepts, however, I'd say those are much more advanced and will only serve to conflate someone's understanding if they're new to react. Not to worry you WILL eventually encounter them, as for me I may or may not make an advanced guide, I suppose it depends on demand either way, let me know in the comments, and thank you very very much for reading this far <3 (◠﹏◠).
Edit: to include css, import your css file in index.html as you normally would ( doing a webpack config is a bit too much for introductory purposes ).
Top comments (10)
Thanks steffanboodhoo, for sharing the amazing post !
This really has a huge chunk of information for any beginner to get stared with React. I really appreciate the efforts you put up while writing the whole thing out 👍.
thank you, really appreciate the appreciation 😁
Best react tutorial in the game.
Many thanks ! many thanks !
This was a good react introduction.
thank you !
hi hi, thanks for the feedback, I'll address these one at a time
@using something like create-react-app,
I mentioned in the post, i'll reiterate here, sometimes the amount of boilerplate code and files can feel overwhelming to someone who's new to the an ecosystem, in my own experience when struggling to learn things, I feel as if I understand a lot better when things are done from 'scratch' almost.
@using props instead of params,
the initial thinking behind it was to relate it to a function however I think on this you're right, it will be easier to transition between tutorials if I used the more standard props
@destructuring in the method signature
I did it for readability but at the end of the article in conventions section as well as in the more network example, I used destructuring in the signature and explained that this is convention
@using strictMode
You're right this would definitely help with debugging, I may edit and add in
@using 'set' vs 'update'
I've seen both across many codebases
@useEffect example
The example isn't meant to be optimal for efficiency rather for showcasing the different parts of useEffect, same goes for things like useMemo, again this is meant to be someone's introduction, as I described above things are made needlessly verbose at times just demonstration and explanatory purposes.
@react router
Again, key word being simplicity and yes the point of any routing system in a frontend framework is to not refresh the page which is why we even bother using NavLink instead of a normal anchor tag
thanks again, I shall make some of the suggested changes once I feel they keep understanding from a beginner's POV optimized.
This is amazing and thanks!
thank you ! 😁
Thanks so much for this. Simple yet comprehensive post for beginners like myself.