Skip to content

Commit b80327f

Browse files
authored
Merge pull request #822 from Lemoncode/refactor/react-01-previous-and-02-base
1º PULL REQUEST- REACT: 01-previous and 02-base folders
2 parents 83210a9 + 8b47274 commit b80327f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1537
-1060
lines changed
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
# 01 Previous - Hi React
2+
3+
## Summary
4+
5+
In this example we are going to create a _codesandbox_ to understand the first concepts of React and the main reasons why we need a library like this.
6+
[Here you have the complete example that we are going to develop.](https://codesandbox.io/p/sandbox/react-concepts-rncyq4)
7+
8+
To begin, we will start from a vanilla JavaScript project and gradually add features that bring us closer to the approach proposed by React. The goal is to see how React solves common web development problems in a more elegant and powerful way.
9+
10+
## Step by step
11+
12+
- Rename the file _index.mjs_ to _index.js_ and update the reference in _index.html_.
13+
- Comment out all the content of _index.js_.
14+
- In _index.html_ render a static list of users:
15+
16+
_index.html_
17+
18+
```diff
19+
<!DOCTYPE html>
20+
<html>
21+
<head>
22+
<title>JavaScript Sandbox</title>
23+
<meta charset="UTF-8" />
24+
</head>
25+
26+
<body>
27+
- <div id="app"></div>
28+
+ <div id="app">
29+
+ <h4>Lista de usuarios</h4>
30+
+ <div>1955: Rick Sánchez</div>
31+
+ <div>8765: Beth Harmon</div>
32+
+ <div>7562: Farrokh Bulsara</div>
33+
+ </div>
34+
<script src="./index.js" type="module"></script>
35+
</body>
36+
</html>
37+
```
38+
39+
This works, but frameworks like React offer us a different approach: they allow us to dynamically transform the DOM in the client. This way, the server only delivers a basic HTML along with a JavaScript file that generates the interface.
40+
41+
We leave the HTML empty and move the list into our _index.js_:
42+
43+
_index.html_
44+
45+
```diff
46+
<!DOCTYPE html>
47+
<html>
48+
<head>
49+
<title>JavaScript Sandbox</title>
50+
<meta charset="UTF-8" />
51+
</head>
52+
53+
<body>
54+
+ <div id="app"></div>
55+
- <div id="app">
56+
- <h4>Lista de usuarios</h4>
57+
- <div>1955: Rick Sánchez</div>
58+
- <div>8765: Beth Harmon</div>
59+
- <div>7562: Farrokh Bulsara</div>
60+
- </div>
61+
<script src="./index.js" type="module"></script>
62+
</body>
63+
</html>
64+
```
65+
66+
_index.js_:
67+
68+
```diff
69+
+ import "./styles.css";
70+
71+
+ document.getElementById("app").innerHTML = `
72+
+ <h4>Lista de usuarios</h4>
73+
+ <div>1955: Rick Sánchez</div>
74+
+ <div>8765: Beth Harmon</div>
75+
+ <div>7562: Farrokh Bulsara</div>
76+
+ `;
77+
```
78+
79+
Now the content is generated by JavaScript. We can confirm that it’s the JavaScript file that generates the content.
80+
81+
### Components
82+
83+
Let’s start breaking our list into parts.We separate the title and the list:
84+
85+
````diff
86+
import "./styles.css";
87+
88+
+ const Header = () => {
89+
+ return `<h4>Lista de usuarios</h4>`;
90+
+ };
91+
92+
+ const List = () => {
93+
+ return `
94+
+ <div>
95+
+ <div>1955: Rick Sánchez</div>
96+
+ <div>8765: Beth Harmon</div>
97+
+ <div>7562: Farrokh Bulsara</div>
98+
+ </div>`;
99+
+ };
100+
101+
document.getElementById("app").innerHTML = `
102+
+ ${Header()}
103+
+ ${List()}
104+
- <h4>Lista de usuarios</h4>
105+
- <div>1955: Rick Sánchez</div>
106+
- <div>8765: Beth Harmon</div>
107+
- <div>7562: Farrokh Bulsara</div>
108+
`;
109+
```
110+
111+
This functions we just created, in React, are components. That is, **in React, components are functions.** For now, these components return a piece of our application, in this case the title and the list, which render something in the DOM.
112+
113+
### Props
114+
115+
Now let’s create a component that renders each user in the DOM. To do this, we’ll create a component (function) that receives a user object with an `id` and `name`:
116+
117+
```diff
118+
import "./styles.css";
119+
120+
const Header = () => {
121+
return `<h4>Lista de usuarios</h4>`;
122+
};
123+
124+
+ const User = (props) => {
125+
+ return `<div>${props.id}: ${props.name}</div>`;
126+
+ };
127+
128+
const List = () => {
129+
return `
130+
<div>
131+
+ ${User({id: 1955, name 'Rick Sánchez'})}
132+
+ ${User({id: 8765, name 'Beth Harmon'})}
133+
+ ${User({id: 7562, name 'Farrokh Bulsara'})}
134+
- <div>1955: Rick Sánchez</div>
135+
- <div>8765: Beth Harmon</div>
136+
- <div>7562: Farrokh Bulsara</div>
137+
</div>`;
138+
};
139+
140+
document.getElementById("app").innerHTML = `
141+
${Header()}
142+
${List()}
143+
`;
144+
````
145+
146+
In React jargon, the input arguments we pass to components are known as `props`. A bit later we’ll see that in React, the syntax for running a component is very different from this. However, it’s very important to keep in mind that even though the syntax is different, in the end what we’re doing is invoking functions and passing them input arguments.
147+
148+
Let’s get a little closer to what a real application would do and simulate that the data we display in the list comes from an API. For this, let’s create a file _./api.js_.
149+
150+
```js
151+
export const getUsers = () => [
152+
{ id: 1955, name: "Rick Sánchez" },
153+
{ id: 8765, name: "Beth Harmon" },
154+
{ id: 7562, name: "Farrokh Bulsara" },
155+
];
156+
```
157+
158+
When invoking it inside the `List` function, we can directly use a `map` method to execute the `User` function for each element of the array, no matter how many there are.
159+
160+
```diff
161+
+ import { getUsers } from './api';
162+
import "./styles.css";
163+
164+
const Header = () => {
165+
return `<h4>Lista de usuarios</h4>`;
166+
};
167+
168+
+ const User = (props) => {
169+
+ return `<div>${props.id}: ${props.name}</div>`;
170+
+ };
171+
172+
const List = () => {
173+
+ const users = getUsers();
174+
return `
175+
<div>
176+
+ ${users.map(user=>User(user)).join('')}
177+
- ${User({id: 1955, name 'Rick Sánchez'})}
178+
- ${User({id: 8765, name 'Beth Harmon'})}
179+
- ${User({id: 7562, name 'Farrokh Bulsara'})}
180+
</div>`;
181+
};
182+
183+
document.getElementById("app").innerHTML = `
184+
${Header()}
185+
${List()}
186+
`;
187+
```
188+
189+
In React, however, the `props` argument is a single parameter: an object to which I can pass whatever I want. Let’s adapt the code.
190+
191+
```diff
192+
import { getUsers } from "./api";
193+
import "./styles.css";
194+
195+
const Header = () => {
196+
return `<h4>Lista de usuarios</h4>`;
197+
};
198+
199+
- const User = (props) => {
200+
+ const User = ({ user }) => {
201+
- return `<div>${props.id}: ${props.name}</div>`;
202+
+ return `<div>${user.id}: ${user.name}</div>`;
203+
};
204+
205+
const List = () => {
206+
const users = getUsers();
207+
return `
208+
<div>
209+
- ${users.map((user) => User(user)).join("")}
210+
+ ${users.map((user) => User({ user })).join("")}
211+
</div>`;
212+
};
213+
214+
document.getElementById("app").innerHTML = `
215+
${Header()}
216+
${List()}
217+
`;
218+
```
219+
220+
### Reactivity
221+
222+
Let’s try to render a random number for each element, calculated at the moment the component is invoked.
223+
224+
```diff
225+
const User = ({ user }) => {
226+
+ const randomNumber = Math.random();
227+
- return `<div>${user.id}: ${user.name}</div>`;
228+
+ return `<div>${user.id}: ${user.name} - ${randomNumber}</div>`;
229+
};
230+
```
231+
232+
If we update it with a setTimeout, we see the value changes in the console, but the interface does not update:
233+
234+
```diff
235+
const User = ({ user }) => {
236+
- const randomNumber = Math.random();
237+
+ let randomNumber = Math.random();
238+
+ setTimeout(() => {
239+
+ randomNumber = Math.random();
240+
+ console.log(randomNumber);
241+
+ }, 3000);
242+
return `<div>${user.id}: ${user.name} - ${randomNumber}</div>`;
243+
};
244+
```
245+
246+
Why doesn’t the interface refresh after the three seconds of the setTimeout? Try to think of the answer...
247+
248+
The explanation is simple: functions are executed only once. At that moment they return something that generates a fragment of HTML. That initial result is what gets injected into the DOM and doesn’t change again, even though the internal logic of the function (like the value of `randomNumber`) does get updated later.
249+
250+
If we look at the console, we see that the value of `randomNumber` is indeed recalculated, but the interface doesn’t reflect that change. This happens because the DOM is not automatically linked to the data of our application.
251+
252+
And this is where libraries like React come in. Their main value is that they incorporate reactivity: they allow us to keep the application state and the user interface in sync.
253+
254+
In React, states are the key piece to persist and manage data. Every time a state changes, React re-executes the components that depend on it, ensuring the interface updates and stays aligned with the most recent information.
255+
256+
### Events and persistence
257+
258+
```diff
259+
const List = () => {
260+
- const users = getUsers();
261+
+ let users = getUsers();
262+
263+
+ const handleClick = () => {
264+
+ alert("button clicked!");
265+
+ users = [...users, { id: 1234, name: "John Doe" }];
266+
+ };
267+
268+
return `
269+
<div>
270+
${users.map((user) => User({ user })).join("")}
271+
+ <button onclick="javascript:handleClick()">Add user</button>
272+
</div>`;
273+
};
274+
```
275+
276+
The button appears but when clicking it, not even the alert shows up. What’s going on?
277+
Again, when `List` is executed, the `handleClick` function is created. However, that function doesn’t run until we click the button, and when that happens, the function no longer exists, because the `List` function has already executed and died.
278+
279+
This is another problem React solves, since it allows us to persist data and functions between executions of our components.
280+
281+
To leave the example ready for the next exercise, let’s make the following change:
282+
283+
```diff
284+
+ export default function App() {
285+
+ return `
286+
+ ${Header()}
287+
+ ${List()}
288+
+ `;
289+
+ }
290+
291+
+ document.getElementById("app").innerHTML = App();
292+
- document.getElementById("app").innerHTML = `
293+
- ${Header()}
294+
- ${List()}
295+
- `;
296+
```

0 commit comments

Comments
 (0)