How to Learn ReactJS Quickly
#WEEK2DAY6: User Interactions, Component Life Cycles, Routing
--
This is still a pretty basic use of React and its ecosystem. But I think with this and everything we know so far. We should be able to at least build and deploy a simple website, not a web app, but a website that is beautiful and impressive.
Handling User Interaction
Simplest Scenario
import React from 'react';class Product extends React.Component {
showPrice() {
alert(this.props.item.price);
}render() {
return <li onClick={() => this.showPrice()}>
<h3>{this.props.item.name}</h3>
<p>{this.props.item.description}</p>
</li>;
}
}export default Product;
HTML vs JSX
HTML events:
<li onclick="...">...</li>
JSX:
<li onClick=...>...</li>
HTML invocation of functions is a string:
<li onclick="showPrice()">...</li>
JSX:
<li onClick={showPrice}>...</li>
<li onClick={() => this.showPrice()}>
HTML default behaviour prevention in JSX:
<a href="#" onClick={(e) => { e.preventDefault();
console.log("Clicked");}}>Click</a>
Change State on Event Trigger
Changing the current components state will be easy, but how do you change the state of a parent component?
Since React is unidirectional down, you can’t go up and access stuff. However you can pass down methods from parents to children. Then the child component can invoke this passed method.
import React from 'react';
import './Catalog.css';
import ProductList from './ProductList';class Catalog extends React.Component {
constructor() {
super();
this.state = { products: [] };fetch("products.json")
.then(response => response.json())
.then(json => {this.setState({products: json})})
.catch(error => console.log(error));
}select(productCode) {
let productList = this.state.products.map(function(p) {
if (p.code === productCode) {
p.selected = (!p.selected);
}
return p;
});
this.setState({products: productList});
}render() {
return <div>
<h2>Wine Catalog</h2>
<ProductList items={this.state.products} selectHandler={this.select}/>
</div>;
}
}export default Catalog;
The the next component does this:
import React from 'react';
import './ProductList.css';
import Product from './Product';class ProductList extends React.Component {
render() {
let products = []; for (let product of this.props.items) {
products.push(<Product item={product}
selectHandler={this.props.selectHandler}/>);
} return <ul>{products}</ul>;
}
}export default ProductList;
It just passes the method from it’s parent to it’s child. Then finally the lowest component does this:
import React from 'react';
import './Product.css'class Product extends React.Component {
render() {
let classToApply = this.props.item.selected? "selected": "";
return <li onClick={() => this.props.selectHandler
(this.props.item.code)} className={classToApply}>
<h3>{this.props.item.name}</h3>
<p>{this.props.item.description}</p>
</li>
}
}export default Product;
It calls the parent’s function passed through the prop. The function in the parent uses the setState method, which refreshes React.
Component Lifecycles
Pre Lifecycle
- Constructor — component doesn’t have access to child components or DOM
Lifecycle (in order of invocation)
- componentWillMount — component is about to be inserted into the DOM
- componentWillReceiveProps — before insertion into DOM, but after receiving props from parent
- shouldComponentUpdate — a method with a return value, that dictates whether the component should continue rendering, has new params nextProps, nextState, can’t set state here
- componentWillUpdate — right right before render()
- componentDidUpdate — right after render(), has two params, previousState and previousProps
- componentDidMount — the component is now inserted into the DOM
- componentWillUnmount — its called right before being removed from the DOM, can’t use setState() here
Grouped and Use Cases
Mounting: This group contains the events related to DOM manipulation:
componentWillMount
,componentDidMount
, andcomponentWillUnmount
Updating via props: Events that are triggered when a component is updated via props
passed by its parent:
componentWillReceiveProps
,shouldComponentUpdate
,componentWillUpdate
, andcomponentDidUpdate
Updating via setState(): Events triggered when a component is updated via setState()
:
shouldComponentUpdate
,componentWillUpdate
, andcomponentDidUpdate
Routing
Our React app is just a single component called App, so how do we simulate page switching?
npm install --save react-router-dom
To add the basic functionality of routing, add this to our index.js:
import React from 'react';
...
import { BrowserRouter } from 'react-router-dom'ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
, document.getElementById('root'));
registerServiceWorker();
Then we go to our App.js:
import React, { Component } from 'react';
import './App.css';
import Catalog from './Catalog';
import About from './About';
import { Switch, Route } from 'react-router-dom'class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">The Catalog App</h1>
<nav>
<ul>
<li><Link to='/'>Catalog</Link></li>
<li><Link to='/about'>About</Link></li>
</ul>
</nav>
</header>
<Switch>
<Route exact path='/' component={Catalog}/>
<Route path='/about' component={About}/>
</Switch>
</div>
);
}
}export default App;
- Catalog at url ‘/’
- About at url ‘/about/’
Also note that the Link to urls must match the Route urls.
To make sure something always renders, use:
<Route path='/about' render={() => (<About data={someData}/>)}/>
or:
<Route path='/footer' children={() => (<Footer />)}/>