Originally published at Codegram's blog
At Codegram we can spend 5 hours a week doing some learning stuff like reading books, doing an online course, or even crafting some pet project to try a new technology. It's really cool and sometimes we even share with our coworkers what are we doing in our biweekly Codegram's Talk Club™️. We want to make a step forward and we decided to create a new learning resource: introducing Codegram's Workshops™️!
Today we are gonna talk about React and Redux. In this first article of this workshop series we are gonna learn how to bootstrap a React application and create our first components. Stay tuned for future updates in this workshop series and let's start!
Introduction
This course is an introduction to React and Redux. We are gonna learn how to create a react application from scratch and deal with components and their weird JSX syntax.
This is not a complete React course and I want to focus on the basics and how to work with a store. I am not gonna cover some topics like styling your components or testing because these are broad topics that can be covered in future workshops. Even though we are gonna use Webpack I am not gonna cover any complex setup either. Let's begin!
Getting started
First of all we need a React application to start working on! There is a package called create-react-app that is very useful to bootstrap something. You can run this command:
$ npx create-react-app --use-npm practical-react-and-redux
By default the command uses yarn
but I prefer npm
. Let's move to that directory and start the development server:
$ cd practical-react-and-redux
$ npm start
Compiled successfully!
You can now view practical-react-and-redux in the browser.
Local: http://localhost:3000
On Your Network: http://192.168.1.12:3000
Note that the development build is not optimized.
To create a production build, use npm run build.
This will open your browser automatically to http://localhost:3000 and if you see the React logo spinning then the application has been compiled successfully and we are ready to start doing some stuff!
Spin up your favorite editor and move on 👏
Components are just functions
Let's start our journey creating our first component but, first of all, what's a component? In the React world a component is just a function that returns something that can be rendered in our DOM. Open the src/App.js
file and remove everything.
Hello world components
We are gonna create our first component: the App
component. Every React application has a root component and although you can name it whatever you want it is usually named App
or Application
(notice the CamelCase
syntax). Write this in your src/App.js
file:
// src/App.js
const App = () => {
return 'Hello World!'
}
export default App
If you visit the http://localhost:3000 you will see our message. Congratulations you just write your first component! 🎉
You are not limited to just Strings
and you can also write plain HTML in there. Try this:
// src/App.js
const App = () => {
return <p>Hello world!</p>
}
export default App
Oh snap! Our application is not working anymore and we got a compilation error. What did you expect? Do you think that looks like JS? Of course not!
There is so magic ✨ behind of this. First of all we are not using plain JS anymore and we started using jsx
. That's a language that compiles to JS and you can think about it as a hybrid between JS and XML (or just HTML).
In order to make that work we need to bring React to the party so let's import it!
// src/App.js
import React from 'react'
const App = () => {
return <p>Hello world!</p>
}
export default App
You might be thinking: why I am importing the React constant if I am not using it? That's true! We are not using the React
constant explicitly but when Webpack compiles this jsx
it's using React.createElement
under the hood to create our component so we need to bring that constant to make it work. If you are curious you can check the main.chunk.js
source file in the browser.
A single component is really boring so let's create a few more components!
Components hierarchy and reusability
Time to create a Dog
🐶 component! As you may notice there is no folder structure to follow but I like to stick to some conventions. I like to organise my components per feature and also having each component in its own folder:
$ mkdir -p src/dogs/components/dog
In your editor create the Dog.js
file in the new folder that we just created with the following content:
// src/dogs/components/dog/Dog.js
import React from 'react'
const Dog = () => {
return (
<div>
<p>Boira</p>
<p>Score: 13/10</p>
</div>
)
}
export default Dog
Now we can use this component in our App
component like this:
// src/App.js
import React from 'react'
import Dog from './dogs/components/dog/Dog'
const App = () => {
return (
<>
<Dog />
<Dog />
</>
)
}
export default App
You might be wondering what's that ugly thing: <>
. That's an empty tag and we need that for two reasons:
- Every React component needs a single root element.
- We don't want extra markup so the
<>
root element is not gonna render anything
Then we are just rendering two Dog
components. As you can see a component can be used as a simple DOM element. We are enhancing the HTML language adding new tags!
Having two dogs named after my dog Boira is cool but it is cooler if we can change dynamically some things in our components. Enter the props
!
Dynamic components using props
A prop or a property is a component's input data. Remember: components are just functions so props is just the single argument that our function is receiving. Since it is an Object
we can use destructuring like this:
// src/dogs/components/dog/Dog.js
import React from 'react'
const Dog = ({ name, score }) => {
return (
<div>
<p>{name}</p>
<p>Score: {score}/10</p>
</div>
)
}
export default Dog
We added the two props: name
and score
. We are also using those variables inside our template escaping the value using curly braces {}
.
If you refresh the page right now you are gonna see nameless dogs without score and that's very sad. You can think about props as a object that include all HTML attributes given to the DOM element representing your component. In other words, you can set the element of these props giving attributes to the <Dog>
tag:
// src/App.js
import React from 'react'
import Dog from './dogs/components/dog/Dog'
const App = () => {
return (
<>
<Dog name="Boira" score="13" />
<Dog name="Black" score="13" />
</>
)
}
export default App
The application works and we have two different dogs now! There is one problem with our current implementation: we could forget to give a value to the score
prop and a dog could end having a null
score 😱.
Props validation: avoid bugs
React doesn't include a built-in package for props validation but there is a package called PropTypes that is included by default when we created the application. We can use this package to validate our props and ensure our components are used correctly:
// src/dogs/components/dog/Dog.js
import React from 'react'
import PropTypes from 'prop-types'
const Dog = ({ name, score }) => {
return (
<div>
<p>{name}</p>
<p>Score: {score}/10</p>
</div>
)
}
Dog.propTypes = {
name: PropTypes.string.isRequired,
score: PropTypes.number.isRequired
}
export default Dog
If you reload the app the application, it is working but we have an error in our console 🤔. We just found a bug! 🐛. In the previous snippet we added prop validations and marked both props as required
. We also marked our score
as a number
but we are giving it as a string
right now. Let's fix this:
// src/App.js
import React from 'react'
import Dog from './dogs/components/dog/Dog'
const App = () => {
return (
<>
<Dog name="Boira" score={13} />
<Dog name="Black" score={13} />
</>
)
}
export default App
The change might be a bit subtle: we replaced "13"
with {13}
. Since we are using curly braces again we are evaluating that 13
as a Javascript number
and the error is gone!
Event handlers as props
New requirements: we want to add a button to increase that score
(we are not gonna add a button to decrease it because dogs are awesome). We need to listen to the click
DOM event for a button and lucky for us React supports a onClick
prop. Let's see how this works!
// src/dogs/components/dog/Dog.js
import React from 'react'
import PropTypes from 'prop-types'
const Dog = ({ name, score }) => {
const onClick = () => {
score += 1
console.log(`This is your new score: ${score}`)
}
return (
<div>
<p>{name}</p>
<p>Score: {score}/10</p>
<button onClick={onClick}>Increase score</button>
</div>
)
}
Dog.propTypes = {
name: PropTypes.string.isRequired,
score: PropTypes.number.isRequired
}
export default Dog
Don't click the button yet! Let's check the code first. We added a new button
element to the template and added the onClick
prop. That prop needs to be assigned to a callback function that will be called when the user presses the button. I added a new function called onClick
(naming is hard sorry) and I am increasing the score
prop and logging a message.
If you visit the page and click the button you will see the message prompted in your console with the new score
value. Yeah you did it! Oh...wait. The template is not being updated, we have another bug! 🐛
Not really 😅, props are supposed to be read-only
and our Dog
component is stateless
. We need to make our component stateful
to be able to change that score
!
Just a quick warning ❗️: When a component's prop changes the component is automatically re-rendered but in our case we are not really changing the prop so the view is not updated.
Conclusion
In this article we learned about how to create a React application from scratch and added our first components. In the next article we are gonna learn about stateful
components using React hooks and also we are gonna do our first steps with Redux.
You can find the code examples in this repository. I also tagged the progress for part 1 in case you want to check the repository at this specific moment.
Cover photo by Lachlan Donald