React.js from scratch
Uday Yadav
Posted on March 30, 2021
I dont like react anymore, all hail vue.js
Intro: React is an Open Source view library created and maintained by Facebook. It's a great tool to render the User Interface (UI) of modern web applications.
React uses a syntax extension of JavaScript called JSX that allows you to write HTML directly within JavaScript. This has several benefits. It lets you use the full programmatic power of JavaScript within HTML, and helps to keep your code readable. For the most part, JSX is similar to the HTML that you have already learned, however there are a few key differences that will be covered throughout these challenges.
For instance, because JSX is a syntactic extension of JavaScript, you can actually write JavaScript directly within JSX. To do this, you simply include the code you want to be treated as JavaScript within curly braces: { 'this is treated as JavaScript code' }
. Keep this in mind, since it's used in several future challenges.
JSX
const JSX = <h1>Hello JSX</h1>;
const JS = <div>
<h1>Hello</h1>
<p>Hello from p tag</p>
</div>
Comment
const JSX = (
<div>
<h1>This is a block of JSX</h1>
<p>Here's a subtitle</p>
{/* this is a comment */}
</div>
);
Render HTML Elements to the DOM
So far, you've learned that JSX is a convenient tool to write readable HTML within JavaScript. With React, we can render this JSX directly to the HTML DOM using React's rendering API known as ReactDOM.
ReactDOM offers a simple method to render React elements to the DOM which looks like this: ReactDOM.render(componentToRender, targetNode)
, where the first argument is the React element or component that you want to render, and the second argument is the DOM node that you want to render the component to.
As you would expect, ReactDOM.render()
must be called after the JSX element declarations, just like how you must declare variables before using them.
const JSX = (
<div id="challenge-node">
<h1>Hello World</h1>
<p>Lets render this to the DOM</p>
</div>
);
// change code below this line
ReactDOM.render(JSX,document.getElementById("challenge-node"))
Define an HTML Class in JSX
Now that you're getting comfortable writing JSX, you may be wondering how it differs from HTML.
So far, it may seem that HTML and JSX are exactly the same.
One key difference in JSX is that you can no longer use the word class
to define HTML classes. This is because class
is a reserved word in JavaScript. Instead, JSX uses className
.
In fact, the naming convention for all HTML attributes and event references in JSX become camelCase. For example, a click event in JSX is onClick
, instead of onclick
. Likewise, onchange
becomes onChange
. While this is a subtle difference, it is an important one to keep in mind moving forward.
const JSX = (
<div className="myDiv">
<h1>Add a class to this div</h1>
</div>
);
Self-Closing JSX Tags
const JSX = (
<div>
<h2>Welcome to React!</h2> <br />
<p>Be sure to close all tags!</p>
<hr />
</div>
);
Create a Stateless Functional Component
Components are the core of React. Everything in React is a component and here you will learn how to create one.
There are two ways to create a React component. The first way is to use a JavaScript function. Defining a component in this way creates a stateless functional component. The concept of state in an application will be covered in later challenges. For now, think of a stateless component as one that can receive data and render it, but does not manage or track changes to that data.
To create a component with a function, you simply write a JavaScript function that returns either JSX or null
. One important thing to note is that React requires your function name to begin with a capital letter.
const MyComponent = function() {
return (
<div>
Hello
</div>
)
}
Create a React Component
The other way to define a React component is with the ES6 class
syntax. In the following example, Kitten
extends React.Component
:
const ChildComponent = () => {
return (
<div>
<p>I am the child</p>
</div>
);
};
class ParentComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>I am the parent</h1>
<ChildComponent />
</div>
);
}
};
React to Render Nested Components
const TypesOfFruit = () => {
return (
<div>
<h2>Fruits:</h2>
<ul>
<li>Apples</li>
<li>Blueberries</li>
<li>Strawberries</li>
<li>Bananas</li>
</ul>
</div>
);
};
const Fruits = () => {
return (
<div>
<TypesOfFruit />
</div>
);
};
class TypesOfFood extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>Types of Food:</h1>
<Fruits />
</div>
);
}
};
Another Example
class Fruits extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h2>Fruits:</h2>
<NonCitrus />
<Citrus />
</div>
);
}
};
class TypesOfFood extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>Types of Food:</h1>
<Fruits />
<Vegetables />
</div>
);
}
};
Pass Props to a Stateless Functional Component
In React, you can pass props, or properties, to child components. Say you have an App
component which renders a child component called Welcome
which is a stateless functional component
const CurrentDate = (props) => {
return (
<div>
<p>The current date is: { props.date }</p>
</div>
);
};
class Calendar extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>What date is it?</h3>
<CurrentDate date={Date()}/>
</div>
);
}
};
Pass an Array as Props
const List = (props) => {
{ /* change code below this line */ }
return <p>{props.tasks.join(", ")}</p>
{ /* change code above this line */ }
};
class ToDo extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>To Do Lists</h1>
<h2>Today</h2>
{ /* change code below this line */ }
<List tasks={["1","1","1"]} />
<h2>Tomorrow</h2>
<List tasks={["1","1","1"]}/>
{ /* change code above this line */ }
</div>
);
}
};
Default props
const ShoppingCart = (props) => {
return (
<div>
<h1>Shopping Cart Component</h1>
<p>{props.items}</p>
</div>
)
};
// change code below this line
ShoppingCart.defaultProps = {
items : 0
}
Overiding Default props
const Items = (props) => {
return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>
}
Items.defaultProps = {
quantity: 0
}
class ShoppingCart extends React.Component {
constructor(props) {
super(props);
}
render() {
return <Items quantity={10}/>
}
};
Use PropTypes to Define the Props You Expect
Importing
import PropTypes from 'prop-types';
Code :
const Items = (props) => {
return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>
};
Items.propTypes = {
quantity : PropTypes.number.isRequired
}
Items.defaultProps = {
quantity: 0
};
class ShoppingCart extends React.Component {
constructor(props) {
super(props);
}
render() {
return <Items />
}
};
Access Props Using this.props
The ES6 class component uses a slightly different convention to access props.
Anytime you refer to a class component within itself, you use the this
keyword. To access props within a class component, you preface the code that you use to access it with this
. For example, if an ES6 class component has a prop called data
, you write {this.props.data}
in JSX.
class ReturnTempPassword extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<p>Your temporary password is: <strong>{this.props.tempPassword}</strong></p>
</div>
);
}
};
class ResetPassword extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h2>Reset Password</h2>
<h3>We've generated a new temporary password for you.</h3>
<h3>Please reset this password from your account settings ASAP.</h3>
<ReturnTempPassword tempPassword="xxxxxxxx" />
</div>
);
}
};
Review Using Props with Stateless Functional Components
A stateless functional component is any function you write which accepts props and returns JSX. A stateless component, on the other hand, is a class that extends React.Component
, but does not use internal state (covered in the next challenge). Finally, a stateful component is a class component that does maintain its own internal state. You may see stateful components referred to simply as components or React components.
A common pattern is to try to minimize statefulness and to create stateless functional components wherever possible. This helps contain your state management to a specific area of your application. In turn, this improves development and maintenance of your app by making it easier to follow how changes to state affect its behavior.
class CampSite extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Camper/>
</div>
);
}
};
class Camper extends React.Component {
constructor(props){
super(props)
}
render(){
return (
<div>
<p>{this.props.name}</p>
</div>
)
}
}
Camper.defaultProps = {
name : "CamperBot"
}
Camper.propTypes = {
name : PropTypes.string.isRequired
}
Create a Stateful Component
One of the most important topics in React is state
. State consists of any data your application needs to know about, that can change over time. You want your apps to respond to state changes and present an updated UI when necessary. React offers a nice solution for the state management of modern web applications.
You create state in a React component by declaring a state
property on the component class in its constructor
. This initializes the component with state
when it is created. The state
property must be set to a JavaScript object
. Declaring it looks like this:
this.state = {
// describe your state here
}
Render State in the User Interface
Once you define a component's initial state, you can display any part of it in the UI that is rendered. If a component is stateful, it will always have access to the data in state
in its render()
method. You can access the data with this.state
.
If you want to access a state value within the return
of the render method, you have to enclose the value in curly braces.
State
is one of the most powerful features of components in React. It allows you to track important data in your app and render a UI in response to changes in this data. If your data changes, your UI will change. React uses what is called a virtual DOM, to keep track of changes behind the scenes. When state data updates, it triggers a re-render of the components using that data - including child components that received the data as a prop. React updates the actual DOM, but only where necessary. This means you don't have to worry about changing the DOM. You simply declare what the UI should look like.
Note that if you make a component stateful, no other components are aware of its state
. Its state
is completely encapsulated, or local to that component, unless you pass state data to a child component as props
. This notion of encapsulated state
is very important because it allows you to write certain logic, then have that logic contained and isolated in one place in your code.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'freeCodeCamp'
}
}
render() {
return (
<div>
<h1>{this.state.name}</h1>
</div>
);
}
};
Render State in the User Interface Another Way
There is another way to access state
in a component. In the render()
method, before the return
statement, you can write JavaScript directly. For example, you could declare functions, access data from state
or props
, perform computations on this data, and so on. Then, you can assign any data to variables, which you have access to in the return
statement.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'freeCodeCamp'
}
}
render() {
const name = this.state.name
return (
<div>
<h1>{this.state.name}</h1>
</div>
);
}
};
this.state Section { important }
Set State with this.setState
There is also a way to change the component's state
. React provides a method for updating component state
called setState
. You call the setState
method within your component class like so: this.setState()
, passing in an object with key-value pairs. The keys are your state properties and the values are the updated state data. For instance, if we were storing a username
in state and wanted to update it, it would look like this:
this.setState({
username: 'Lewis'
});
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'Initial State'
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
name : "React Rocks!"
})
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click Me</button>
<h1>{this.state.name}</h1>
</div>
);
}
};
Bind 'this' to a Class Method
In addition to setting and updating state
, you can also define methods for your component class. A class method typically needs to use the this
keyword so it can access properties on the class (such as state
and props
) inside the scope of the method. There are a few ways to allow your class methods to access this
.
One common way is to explicitly bind this
in the constructor so this
becomes bound to the class methods when the component is initialised. You may have noticed the last challenge used this.handleClick = this.handleClick.bind(this)
for its handleClick
method in the constructor. Then, when you call a function like this.setState()
within your class method, this
refers to the class and will not be undefined
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "Hello"
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
text: "You clicked!"
});
}
render() {
return (
<div>
<button onClick = {this.handleClick}>Click Me</button>
<h1>{this.state.text}</h1>
</div>
);
}
};
Use State to Toggle an Element
Sometimes you might need to know the previous state when updating the state. However, state updates may be asynchronous - this means React may batch multiple setState()
calls into a single update. This means you can't rely on the previous value of this.state
or this.props
when calculating the next value. So, you should not use code like this:
this.setState({
counter: this.state.counter + this.props.increment
});
Instead, you should pass setState
a function that allows you to access state and props. Using a function with setState
guarantees you are working with the most current values of state and props. This means that the above should be rewritten as:
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
You can also use a form without props
if you need only the state
:
this.setState(state => ({
counter: state.counter + 1
}));
Counter
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.increment = this.increment.bind(this);
this.decrement = this.decrement.bind(this);
this.reset = this.reset.bind(this);
}
reset() {
this.setState({
count: 0
});
}
increment() {
this.setState(state => ({
count: state.count + 1
}));
}
decrement() {
this.setState(state => ({
count: state.count - 1
}));
}
render() {
return (
<div>
<button className='inc' onClick={this.increment}>Increment!</button>
<button className='dec' onClick={this.decrement}>Decrement!</button>
<button className='reset' onClick={this.reset}>Reset</button>
<h1>Current Count: {this.state.count}</h1>
</div>
);
}
};
React: Create a Controlled Input
class ControlledInput extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
this.setState({
input: event.target.value
});
}
render() {
return (
<div>
<input value = {this.state.input} onChange = {this.handleChange.bind(this)}/>
<h4>Controlled Input:</h4>
<p>{this.state.input}</p>
</div>
);
}
};
React: Create a controlled form part - ii
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = {
input: '',
submit: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({
input: event.target.value
});
}
handleSubmit(event) {
event.preventDefault()
this.setState({
submit: this.state.input
});
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
value={this.state.input}
onChange={this.handleChange} />
<button type='submit'>Submit!</button>
</form>
<h1>{this.state.submit}</h1>
</div>
);
}
};
Pass State as Props to Child Components
class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'CamperBot'
}
}
render() {
return (
<div>
<Navbar name={this.state.name} />
</div>
);
}
};
class Navbar extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>Hello, my name is: {this.props.name} </h1>
</div>
);
}
};
Pass a Callback as Props
class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
inputValue: event.target.value
});
}
render() {
return (
<div>
<GetInput
input={this.state.inputValue}
handleChange={this.handleChange}/>
<RenderInput
input={this.state.inputValue}/>
</div>
);
}
};
class GetInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Get Input:</h3>
<input
value={this.props.input}
onChange={this.props.handleChange}/>
</div>
);
}
};
class RenderInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Input Render:</h3>
<p>{this.props.input}</p>
</div>
);
}
};
Component LifeCycle
Example :
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ""
};
this.handleEnter = this.handleEnter.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
}
// change code below this line
componentDidMount() {
document.addEventListener("keydown", this.handleKeyPress);
}
componentWillUnmount() {
document.removeEventListener("keydown", this.handleKeyPress);
}
// change code above this line
handleEnter() {
this.setState({
message: this.state.message + "You pressed the enter key! "
});
}
handleKeyPress(event) {
if (event.keyCode === 13) {
this.handleEnter();
}
}
render() {
return (
<div>
<h1>{this.state.message}</h1>
</div>
);
}
}
Optimize Re-Renders with shouldComponentUpdate
class OnlyEvens extends React.Component {
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps) {
if (nextProps.value % 2 == 0) {
return true;
}
return false;
}
componentDidUpdate() {
console.log('Component re-rendered.');
}
render() {
return <h1>{this.props.value}</h1>
}
};
class Controller extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 0
};
this.addValue = this.addValue.bind(this);
}
addValue() {
this.setState({
value: this.state.value + 1
});
}
render() {
return (
<div>
<button onClick={this.addValue}>Add</button>
<OnlyEvens value={this.state.value}/>
</div>
);
}
};
Inline Styling
const styles = {
color: 'purple',
fontSize: 40,
border: "2px solid purple",
};
class Colorful extends React.Component {
render() {
// change code below this line
return (
<div style={styles}>Style Me!</div>
);
// change code above this line
}
};
Use Advanced JavaScript in React Render Method
const inputStyle = {
width: 235,
margin: 5
}
class MagicEightBall extends React.Component {
constructor(props) {
super(props);
this.state = {
userInput: '',
randomIndex: ''
}
this.ask = this.ask.bind(this);
this.handleChange = this.handleChange.bind(this);
}
ask() {
if (this.state.userInput) {
this.setState({
randomIndex: Math.floor(Math.random() * 20),
userInput: ''
});
}
}
handleChange(event) {
this.setState({
userInput: event.target.value
});
}
render() {
const possibleAnswers = [
'It is certain',
];
const answer = possibleAnswers[this.state.randomIndex];
return (
<div>
<input
type="text"
value={this.state.userInput}
onChange={this.handleChange}
style={inputStyle} /><br />
<button onClick={this.ask}>
Ask the Magic Eight Ball!
</button><br />
<h3>Answer:</h3>
<p>
{answer}
</p>
</div>
);
}
};
Coditional render
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
display: true
}
this.toggleDisplay = this.toggleDisplay.bind(this);
}
toggleDisplay() {
this.setState({
display: !this.state.display
});
}
render() {
// change code below this line
if (this.state.display) {
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
<h1>Displayed!</h1>
</div>
);
} else {
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
</div>
);
}
}
};
Use && for a More Concise Conditional
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
display: true
}
this.toggleDisplay = this.toggleDisplay.bind(this);
}
toggleDisplay() {
this.setState(state => ({
display: !state.display
}));
}
render() {
// change code below this line
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
{this.state.display && <h1>Displayed!</h1>}
</div>
);
}
};
Use a Ternary Expression for Conditional Rendering
const inputStyle = {
width: 235,
margin: 5
}
class CheckUserAge extends React.Component {
constructor(props) {
super(props);
this.state = {
userAge: '',
input: ''
}
this.submit = this.submit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({
input: e.target.value,
userAge: ''
});
}
submit() {
this.setState(state => ({
userAge: state.input
}));
}
render() {
const buttonOne = <button onClick={this.submit}>Submit</button>;
const buttonTwo = <button>You May Enter</button>;
const buttonThree = <button>You Shall Not Pass</button>;
return (
<div>
<h3>Enter Your Age to Continue</h3>
<input
style={inputStyle}
type="number"
value={this.state.input}
onChange={this.handleChange} /><br />
{
this.state.userAge === ''
? buttonOne
: this.state.userAge >= 18
? buttonTwo
: buttonThree
}
</div>
);
}
};
Render connditionally from props
class Results extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<h1>
{
this.props.fiftyFifty ?
'You Win!' :
'You Lose!'
}
</h1>
)
};
};
class GameOfChance extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 1
}
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
counter: this.state.counter + 1
});
}
render() {
const expression = Math.random() >= .5;
return (
<div>
<button onClick={this.handleClick}>Play Again</button>
<Results fiftyFifty={expression} />
<p>{'Turn: ' + this.state.counter}</p>
</div>
);
}
};
Change Inline CSS Conditionally Based on Component State
class GateKeeper extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ input: event.target.value })
}
render() {
let inputStyle = {
border: '1px solid black'
};
// change code below this line
if (this.state.input.length > 15) {
inputStyle = {
border: '3px solid red'
};
}
// change code above this line
return (
<div>
<h3>Don't Type Too Much:</h3>
<input
type="text"
style={inputStyle}
value={this.state.input}
onChange={this.handleChange} />
</div>
);
}
};
Use Array.map() to Dynamically Render Elements
const textAreaStyles = {
width: 235,
margin: 5
};
class MyToDoList extends React.Component {
constructor(props) {
super(props);
// change code below this line
this.state = {
userInput: '',
toDoList: []
}
// change code above this line
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleSubmit() {
const itemsArray = this.state.userInput.split(',');
this.setState({
toDoList: itemsArray
});
}
handleChange(e) {
this.setState({
userInput: e.target.value
});
}
render() {
const items = this.state.toDoList.map(i => <li>{i}</li>); // change code here
return (
<div>
<textarea
onChange={this.handleChange}
value={this.state.userInput}
style={textAreaStyles}
placeholder="Separate Items With Commas" /><br />
<button onClick={this.handleSubmit}>Create List</button>
<h1>My "To Do" List:</h1>
<ul>
{items}
</ul>
</div>
);
}
};
Give Sibling Elements a Unique Key Attribute
const renderFrameworks = frontEndFrameworks.map((item) =>
<li key={item+1}>{item}</li>
);
Use Array.filter() to Dynamically Filter an Array
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [
{
username: 'Jeff',
online: true
},
{
username: 'Alan',
online: false
},
{
username: 'Mary',
online: true
},
{
username: 'Jim',
online: false
},
{
username: 'Sara',
online: true
},
{
username: 'Laura',
online: true
}
]
}
}
render() {
const usersOnline = this.state.users.filter(i => i.online == true); // change code here
const renderOnline = usersOnline.map((i) => <li key={i.username + 1}>{i.username}</li>); // change code here
return (
<div>
<h1>Current Online Users:</h1>
<ul>
{renderOnline}
</ul>
</div>
);
}
};
Render React on the Server with renderToString
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div/>
}
};
// change code below this line
ReactDOMServer.renderToString(<App />);
Posted on March 30, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.