Done: No Status: In Progress
Many people starting out get overwhelmed by all the things happening in the React ecosystem. There's this idea that what happens in React is magic and that getting started with React is super complicated unless you use tools like create-react-app .
And honestly, it's not as widely documented that you only need 5 minutes to actually inject React into your page. Dan Abramov has been trying to raise awareness to this and he's been doing an amazing job, so taking from his idea let's make you believe the 5 minutes statement.
Well, first step is finding the files to insert, and these can be found at UNPKG. This is like a giant CDN of all the awesome libraries and frameworks around the world.
If you go to the URL https://unpkg.com/react@16/ you will see all the contents React has and in there you have two folders:
The folder UMD(Universal Module Definition)
is the one we want as this one is understood by the browser without any bundler.
You need to also go to https://unpkg.com/react-dom@16/ to get the URL of development version of React Dom as we also need this library to make our project work.
The two links are:
-
Curious about the
cjs
folder?The
cjs
folder is for use with NPM and the one used when you import react with npm andcjs
meansCommonJS
and is also what is used is used in node for example.
To start we need an initial HTML file. I use VSCode, so here, to create a simple HTML file you just need to type !
and then tab
and you will have a starter file to insert the two links with script tags. Mine looks like this:
https://gist.github.com/00447809e319edd974bd9b2d0f4215f4
Let's now write some react code!
JSX (JavaScript XML) may look confusing and magical but in reality it's just some syntax sugar over the React.createElement
function. If we don't want any type of npm or webpack magic we can just use this function that has the same effect so let's take a look at it.
Knowing this, we can create a simple div that has some text inside and a class to be styled in CSS, like so:
https://gist.github.com/4800a051e058b6810a14d048d3d15832
If you reload the page, nothing will happen. This is where [react-dom](https://github.com/facebook/react/tree/master/packages/react-dom)
comes into play because react itself can be rendered into a lot of places, like native apps for iOS and Android, TV's, PDF and really anything you set your mind to.
react-dom
is the library we want in order to render it into the web and then we need the ReactDom.render
function. This function takes two arguments:
- The element we want to render. In this case, that's is our wrapper function
- Where we want to render it to. In this function you can render it straight into the body but I would always advise to create a new element like a main and render it there. To get this element we will use
[document.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
and pass it our#app.
In code this would look something like:
https://gist.github.com/5ba69cd44608831236a806a953f50599
If you reload the page, you can see our wrapper but it doesn't really look nice so let's add some CSS to it:
https://gist.github.com/9dc745f523780e851c120ca62b9dd4c3
And now you should see something like this when you open your index.html in your browser:
So we got the basics of showing an element and now let's get into some more interactivity by using React's Component State.
In this part we are going to create the best App ever. We will get a dog photo from https://dog.ceo/api/breed/akita/images/random
, show it on the page, and also add a button to refetch another dog photo. Trust me it's going to be great!
The first thing we need to do is to make our function be a [React.Component](https://reactjs.org/docs/react-component.html)
. The main difference for us is that these Components
can hold state and the functions can't.
The state contains data specific to this component that may change over time. The state is user-defined, and it should be a plain JavaScript object. - via reactjs.org
We should also consider that if we attach this state to a rendered element, this element will update once the state changes.
For our use case we will need am image property in our state that will have the source for our image. So our Wrapper
should look something like:
https://gist.github.com/eb820c32c0591543448a33121e84044c
Wow! So this changed a lot so let's through what is going on:
We now have a class instead of a simple function, you can read more about classes on the Mozilla Developer Docs. We also extend out of React.Component
, which means that React.Component is our parent class and we inherit methods from it.
The constructor method is a special method for creating and initialising an object created with a class. There can only be one special method with the name "constructor" in a class. A
SyntaxError
will be thrown if the class contains more than one occurrence of a constructor method. - via developer.mozilla.org
A constructor can use the super keyword to call the constructor of the super class.
After creating our base class we set the initial state that will be changed with this.state = { image: null };
the reason this is null in the start is because we don't have an image yet. Then in the render function we return the HTML element react will create for us.
Next step is creating the image tag that will have our awesome puppy:
https://gist.github.com/bdd7c58f4bcd061c6cbde4d33ebe710c
We have seen this pattern before when creating our Wrapper
component. The only thing we changed here from our Wrapper
component is that we now receive an argument with all the props passed to the element. In the props object there is a parameter called source and set that as the src
attribute of the image. We also don't pass any children as images don't really have any elements inside them.
Now for the button we do something similar:
https://gist.github.com/e552aa893c23fc1a1637e875fbf59cb7
Here we receive the a function that will be called when this button is clicked and will get another random puppy.
We have all the pieces and let's now get this all working together in our Wrapper
component by attaching these two elements to the Wrapper
class and it's state.
To place these two elements as children of the Wrapper
, we need to pass them as the arguments of the React.createElement
function. Any argument after the second one will be seen as a children by React.
Our Wrapper
will look something like:
https://gist.github.com/8c4d11c08f72cf6903fff07aa93b46b1
Now it's time we actually fetch the image and for that we will use the [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
api provided by most modern browsers.
Let's do that in a separate function and call it when the component mounts on the page:
https://gist.github.com/d31720cb3185bc0f64d5ceba7466c73c
First thing we did was create a getImage
function and in that function we get the image. When we got it we called setState
, which is how you change the state of a component in React. Assigning the state to a new object won't work because React won't re-render the component.
In componentDidMount
we called the getImage
function we just created and this will populate this.state.image
. That we can pass it to the img
element and show our new puppy. We also pass our getImage
function to the button so that the user can request a new puppy.
The bind in the constructor is done because functions have their own scope and not the scope of the class
it's a part of. When we have a function like this, the value of this
is no longer the class methods like setState
but it's instead the own function. The this
keyword is confusing when you first hear about so you can read more about it in the Mozilla Developer Docs.
We can do two things, we can bind it manually with this.getImage = this.getImage.bind(this)
and this will change the scope to be the class. Or we can use arrow functions as these ones have no scope. In this case, for clarity, I decided to go with the first one.
You can see a live version of our awesome website here: https://react-no-jsx.now.sh
Also the code here: https://gist.github.com/SaraVieira/c99fd3ff7177b86c14209df92483f784
So you want some JSX ah?
I like you! You live on the edge! I would say that to start you can go on the Babel's online playground and play with it a bit. Once you understand it and want to apply to this exercise without much setup you can follow this guide by the react team.
After this you can start playing on codesanbox that offers the whole environment online. Then go ahead and download [create-react-app](https://github.com/facebook/create-react-app)
to get React and JSX set up on your own machine.
Hope this cleared some of the magic React sometimes feels to have and got you excited about it. Even if you already know React I hope this has taught you some new fundamentals you might not be aware of.
Go and build dope stuff with React! ⚛️
Thank you to Dan Abramov for bringing this to light!