React Fundamentals IV
Kay Ashaolu
Events
- We are now to the point where we can learn how to incorporate events
- How do we execute data when someone clicks on a particular button?
- We use the event properties that you would customarily find in HTML
Example
import React from "react";
import ReactDOM from "react-dom";
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
Example
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
There's a lot going on
- This code creates a single button that has state indiciating whether it is on or off
- This state is toggled whenever the button is clicked
- This behavior is achieved by a few lines of code in the example
Constructor
- this.handleClick = this.handleClick.bind(this);
- What is this doing?
- Remember when I spoke about arrow functions and how it's important to use them?
- This is why: if you do not do this, then refernces to this function outside of the class will not have access to the this variable
- This line binds that function to the instance of the class in which it is caused
handleclick()
- We define the event handler within the component that we are creating
- This is best practice: continues with the idea that everyting related to the component is within the component
- The function is setting the state to be the opposite of what it is currently
New setState Function
- Note that we are using a different version fo the setState fucntion, that has a parameter called "state"
- This is the proper way of accessing the current state in order to determine what the new state will be
- Do not use this.state directly: unexpected results may occur
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
The render function
- Here we set our handleClick() function to be executed onClick
- Note that there are no quotation marks in setting properties for React when you are setting it to an expression
- This is correct: React will add quotes to the final DOM
Conditional Rendering
- Now we are getting a handle of React
- Its time to demonstrate some capabilities of React to give you a sense of what's possible
- You can conditionally render different components
Example
class UserGreeting extends React.Component {
render() {
return (<h1>Welcome back!</h1>);
}
}
class GuestGreeting extends React.Component {
render() {
return (<h1>Please sign up.</h1>);
}
}
class Greeting extends React.Component {
constructor(props) {
super(props)
}
render() {
if (this.props.isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
}
Example
class LoginButton extends React.Component {
render() {
return (
<button onClick={this.props.onClick}>
Login
</button>
);
}
}
class LogoutButton extends React.Component {
render() {
return (
<button onClick={this.props.onClick}>
Logout
</button>
);
}
}
Example
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
Example
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
Conditional Rendering Example
- There's a lot going on
- We'll go through this step by step
- This also gives a good example of how components can nest within each other and how properties in a parent component can be passed down to its children
Greeting Component
- The Greeting component dependent on the property isLoggedIn renders a different component
- If isLoggedIn is true, render UserGreeting
- If isLoggedIn is false, render GuestGreeting
LoginControl Component
- Note the larger LoginControl Component also determines whether a LoginButton or a LogoutButton is created
- The component also contains a Greeting component
- Note the LoginControl Component connects the onClick event of both buttons to drive the state of the component
- Also the LoginControl passes the current state to the Greeting via properties
Lists and Keys
- One common functionailty is to have lists of objects driven by React
- Since a list can be added to/subtracted from at any point, you do not know how many compoennts you will need beforehand
- For React to be able to keep track of all of the components within a list, we'll need to specify a unique key
- React uses that key to refer to a particular item in a list of components
Example
import React from "react";
import ReactDOM from "react-dom";
class ListItem extends React.Component {
constructor(props) {
super(props);
}
render() {
const value = this.props.value
return (<li>{value}</li>);
}
}
Example
class NumberList extends React.Component {
constructor(props) {
super(props);
}
render() {
const numbers = this.props.numbers;
const listItems = numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
Example Explained: ListItem
- We define a component that comprises of just an element in the list
- With React composing components out of other components is not only easy to do but encouraged
- Enables the creation of a complex design using simple building blocks
Example Explained: NumberList
- In the rendering of a NumberList, a number of ListItems are created
- Note the use of the map() function that enables you to execute the same function over each element in a list
- The result is saved in a constant, which is then added to the render function call
Key Attribute
- If you are creating multlple instances of a component in the same array, its good to specify a key
- A key gives React the ability to target specific instances