In previous articles in this series, I explained my mental models around understanding 1) what React is and how it helps, 2) the hierarchy of React components on a web page, and 3) how React manages the flow of data.
In all of this, I have avoided getting to the specifics of React code as my focus has been on the concepts.
However, I wanted to get into the concepts of the specifics, that is, the nitty-gritty of React's syntax.
A common pitfall of someone who is new to React is to confuse what is a JavaScript thing and what is a React thing.
Hence, in talking about React's syntax, we need a mental model for distinguishing those things that are particular to React.
JSX
As I've mentioned before, React components are essentially a function that returns a web element.
Let's look at an example:
function Button() {
return <button>Click Me!</button>
}
In this (very) simple React component, we see that it is a function that returns an element.
PascalCase
There is one thing here that is specific to React. That is, the function is in PascalCase
(like camelCase
except the first letter is also capitalized).
This subtle difference is for being able to easily distinguish between a React component and an ordinary function.
Since our current component is as basic as it gets, let's incrementally make additional changes so we can point out even more things that are React-specific.
HTML vs. JSX
function Button() {
return (
<button
className="some-class"
disabled={false}
style={{ color: 'red' }}
>
Click Me!
</button>
);
}
So far, I've said that a React component returns a web element, implying an HTML element.
Technically, React returns something-like-HTML and translates it into HTML.
React's syntax is called JavaScript + XML.
The "ML" in HTML stand for "Markup Language."
The "ML" in XML also stands for "Markup Language."
Markup Language
So, what does "Markdown Language" mean?
Let's work backwards.
In human terms, "language" refers to the words that are understood by a community. It is used for a community to communicate with one another.
In computer programming terms, "language" refers to the instructions that are understood by a computer. Specifically, instructions that are understood within a computer environment.
Just as traveling to different countries may require the use of a particular language(s), so too, different computer environments require the use of a particular language(s).
HTML is a language by which the web browser, the computer environment of the web, understands how to construct elements in a web page.
In human terms, there are different types of languages (such as formal vs. informal) for all the various languages.
Similarly, there are different types of computer languages for all the different computer environments.
Just as formal language serves different purposes than informal language (such as writing vs. communicating with friends and family), so too, different computer languages serve different purposes.
"Markup" refers to a type of computer language that is used to construct elements in an application.
This is different from a "programming" language which is a type of computer language for interacting with elements and handling data.
Hypertext Markup Language
Hyper Text Markup Language (HTML) is a particular kind of markup language.
So, what does "hypertext" signify?
The short answer is that "hypertext" is synonymous with the web. So, we can read "hypertext" specifies that HTML is a markup language for the web. We can read it as "Web Markup Language."
I'll provide the technical answer if you're curious.
More technically, "hypertext" refers to text that links to other text.
Back in the 90s, when HTML was invented, the "web" might suggest something different than it does to us today.
Today, we might think of the "web" as the place where we watch videos, comment on our friend's photos, and accomplish other fun and productive tasks. However, back then, a web page would look more like this:
A web page would have been a collection of text as well as links to other pages (with more text).
Interestingly, "web" was a reference to the mesh, or web, of information that could be accessed while navigating between these pages.
In short, "hypertext" being synonymous with "web" meant more sense when HTML was coined than it does to us now.
Putting it all together, "hypertext" means the web, and "markup" + "language" means a computer language for constructing elements in an application.
Again, HTML refers to the language for constructing elements in a web application.
JavaScript + XML
Java Script + XML (JSX) is similar in that it is a markup language. That is, it is a computer language for constructing elements in an application.
The "X" is XML stands for extendible.
In a word, XML is used for passing data that can later on be displayed by a UI. It is not meant for displaying.
To put it in simple terms, XML is a markup language that will be consumed by something else before the data it contains is displayed.
Hence, the addition of "JavaScript" means that JSX is a way to write markup with data.
Similar to HTML, it is a means to creating web elements (since JSX ultimately gets translates to HTML).
Unlike HTML, it can bind/populate/glue data to the the web elements. So, after React translates the JSX to HTML, the web elements can be displayed with the data that was bound to it.
Hence, React has a concept of re-rendering when the data (state and props) bound to web elements is changed.
With that in mind, let's take another look at our example:
function Button() {
return (
<button
className="some-class"
disabled={false}
style={{ color: 'red' }}
>
Click Me!
</button>
);
}
disabled={false}
must be a React/JSX (not HTML) thing because it is binding data to a web element's attribute.
We'll see more examples of this later.
In addition to the major difference of binding data, JSX has a few things that differ from HTML.
Instead of class
, you use className
.
Instead of a style
string, you use an object with the traditional CSS attributes/keys being in camelCase
.
This is something you just memorize and get used to.
Props
function Button({ isDisabled }) {
return (
<button
className="some-class"
disabled={isDisabled}
style={{ color: 'red' }}
>
Click Me!
</button>
);
}
As we've discussed before, "props" (or properties) is a React-specific concept. It is the way you can pass data from a parent component to a child component.
We'll look at how you "use" a component and set "props" in just a minute. But for now, just know that a React component/function "receives" its props from the parent through an object parameter containing all of the props.
Prop Deconstructing
Button({ someProp })
is JavaScript syntax for "deconstructing an object."
We could also do Button(props)
and access a prop by doing props.someProp
. However, deconstructing/plucking the props in the ()
of the function seems to be more popular.
In other words, deconstructing is not "React magic" but receiving a "props" object as an argument is.
With access to a prop, a React component can do different things.
Prop-Attribute Binding
As in the example above, it can bind an attribute to the prop (i.e. disabled={isDisabled}
). In this example, the Button
will be disabled if the component that renders the button provides a isDisabled
prop with a value of true. Otherwise, it won't be disabled.
Dynamic Values
Props can also be used to dynamically derive values for an element's attributes:
function Button({ isDisabled }) {
return (
<button
className={isDisabled ? 'disabled-button' : 'normal-button'}
disabled={disabled}
style={{ color: isDisabled ? 'red': 'blue' }}
>
{isDisabled ? 'Yes' : 'No'}, the button is {isDisabled ? 'disabled' : 'not disabled'}.
</button>
);
}
In JSX, {}
is used to "use" JavaScript to derive values.
Dynamic Rendering
Finally, props can be used to render or not render elements to the browser (not merely different values/attributes):
function Button({ isDisabled, isLoading }) {
return (
<div>
<button
className={isDisabled ? 'disabled-button' : 'normal-button'}
disabled={disabled}
style={{ color: isDisabled ? 'red': 'blue' }}
>
{isDisabled ? 'Yes' : 'No'}, the button is {isDisabled ? 'disabled' : 'not disabled'}.
</button>
{isLoading ? <p>Loading</p> : null}
</div>
);
}
This is useful for showing/hiding things based on props, or tweaking what is shown based on props.
State
As we've discussed before, state and props are both data. State is just data that has been defined in the component itself whereas props is data that has been defined and "passed down" by a parent component.
Since state is data, it can be used to do all the dynamic things we've just discussed.
If the state or props in a component changes, React will re-render/refresh the component with the new elements based on the new data.
As for the syntax of state, let's look at an example:
import { useState } from 'react';
function Button() {
const [hasBeenClicked, setHasBeenClicked] = useState(false);
}
useState
is a function that the React package exports.
It is part of a series of functions that React exports.
These functions that are prefixed with "use" are called React Hooks.
React hooks is obviously a React-specific thing. So if you see a function like use____
then you know it is React-specific code.
React hooks will require an entire article to unpack.
For now, my point is to show that useState
is a React concept.
useState
is a function that "takes in" a default value, and returns an array with the first element containing that default value.
The second value of the array is a "setter" function. It is used for updating the value of the state, telling React to re-render/refresh.
[hasBeenClicked, setHasBeenClicked] = useState(false)
is an example of array deconstructing.
Essentially, with this syntax, you can pluck and name the elements in an array in an easy fashion.
You could also do hasBeenClickedState = useState(false)
and access to the value via hasBeenClickedState[0]
as well as the setter via hasBeenClickedState[1]
.
For obvious reasons, the deconstruction syntax is used. In other words, the deconstructing part is not "React magic," but the returning of the array via useState
is.
Recall, with access to the state, you can do the same dynamic things you could with props:
function Button() {
const [isDisabled, setIsDisabled] = useState(false);
return (
<button disabled={disabled}>
Click Me!
</button>
);
}
Again, to update the state, you call the "setter" function with the new value:
function Button() {
const [isDisabled, setIsDisabled] = useState(false);
return (
<button disabled={disabled} onClick={() => setIsDisabled(true)}>
Click Me!
</button>
);
}
Consuming Components
So far, we've gone over the basic of the React syntax/magic for dynamically rendering web elements.
We've looked at defining React components, but now we need to go over using/consuming React components.
React components are consumed/used from other React components.
In other words, since there is a hierarchy of web elements (and hence, a hierarchy of components), a component will always render at least one other component until you get to the lowest/basic/house component (a component that only renders web elements directly).
To consume/use a React component from another component, here's what you do:
import Button from './Button';
function SignUp() {
return (
<div>
<div>Sign Up</div>
<Button />
</div>
)
}
You 1) import the component, 2) ensure it is named using PascalCase
, and 3) use the component name in place of an element name/tag.
If you want to pass "props," you do so by writing them out as follows:
import { useState } from 'react'
import Button from './Button';
function SignUp() {
const [isSubmitting, setIsSubmitting] = useState(false);
return (
<div>
<div>Sign Up</div>
<Button isDisabled={isSubmitting} onClick={() => setIsSubmitting(true)} />
</div>
)
}
If you want to pass text or other elements/components to another component, you put it between a starting and ending tag:
import { useState } from 'react'
import Button from './Button';
import Form from './Form';
import Heading from './Heading';
function SignUp() {
const [isSubmitting, setIsSubmitting] = useState(false);
return (
<div>
<Form>
<Heading>Sign Up</Heading>
<p>lorem ipsum</p>
<Button
isDisabled={isSubmitting}
onClick={() => setIsSubmitting(true)}
>
Count me, in
</Button>
</Form>
</div>
)
}
When defining a React component/function, you can receive the stuff-between-the-starting-and-ending-tags via a children
prop. This is React magic:
function Form({ children }) {
return <form>{children}</form>;
}
Conclusion
There is definitely a lot more that could be said, but hopefully, this is a good introduction to the syntax of React.
By now, you should have a better understanding as to what is specific to React and what is JavaScript.
In a word, if you can't determine that it's React magic, then it is normal JavaScript.
In future articles, we'll unpack more of that React magic.
Top comments (0)