Refer to the state object anywhere in the component by using the this.state.propertyname syntax:
Refer to the state object in the render() method:
class Car extends React.Component { constructor(props) { super(props); this.state = { brand: "Ford", model: "Mustang", color: "red", year: 1964 }; } render() { return ( <div> <h1>My {this.state.brand}</h1> <p> It is a {this.state.color} {this.state.model} from {this.state.year}. </p> </div> ); }}
To change a value in the state object, use the this.setState() method.
When a value in the state object changes, the component will re-render, meaning that the output will change according to the new value(s).
Add a button with an onClick event that will change the color property:
class Car extends React.Component { constructor(props) { super(props); this.state = { brand: "Ford", model: "Mustang", color: "red", year: 1964 }; } changeColor = () => { this.setState({color: "blue"}); } render() { return ( <div> <h1>My {this.state.brand}</h1> <p> It is a {this.state.color} {this.state.model} from {this.state.year}. </p> <button type="button" onClick={this.changeColor} >Change color</button> </div> ); }}
Always use the setState() method to change the state object, it will ensure that the component knows its been updated and calls the render() method (and all the other lifecycle methods).
Just like HTML, React can perform actions based on user events.
React has the same events as HTML: click, change, mouseover etc.
React events are written in camelCase syntax:
onClick instead of onclick.
React event handlers are written inside curly braces:
onClick={shoot} instead of onClick="shoot()".
<button onClick={shoot}>Take the Shot!</button>
A good practice is to put the event handler as a method in the component class:
Put the shoot function inside the Football component:
class Football extends React.Component { shoot() { alert("Great Shot!"); } render() { return ( <button onClick={this.shoot}>Take the shot!</button> ); }} ReactDOM.render(<Football />, document.getElementById('root'));
For methods in React, the this keyword should represent the component that owns the method.
That is why you should use arrow functions. With arrow functions, this will always represent the object that defined the arrow function.
class Football extends React.Component { shoot = () => { alert(this); /* The 'this' keyword refers to the component object */ } render() { return ( <button onClick={this.shoot}>Take the shot!</button> ); }} ReactDOM.render(<Football />, document.getElementById('root'));
In class components, the this keyword is not defined by default, so with regular functions the this keyword represents the object that called the method, which can be the global window object, a HTML button, or whatever.
Read more about binding this in our React ES6 'What About this?' chapter.
If you must use regular functions instead of arrow functions you have to bind this to the component instance using the bind() method:
Make this available in the shoot function by binding it in the constructor function:
class Football extends React.Component { constructor(props) { super(props) this.shoot = this.shoot.bind(this) } shoot() { alert(this); /* Thanks to the binding in the constructor function, the 'this' keyword now refers to the component object */ } render() { return ( <button onClick={this.shoot}>Take the shot!</button> ); }} ReactDOM.render(<Football />, document.getElementById('root'));
Without the binding, the this keyword would return undefined.
If you want to send parameters into an event handler, you have two options:
Send "Goal" as a parameter to the shoot function, using arrow function:
class Football extends React.Component { shoot = (a) => { alert(a); } render() { return ( <button onClick={() => this.shoot("Goal")}>Take the shot!</button> ); }} ReactDOM.render(<Football />, document.getElementById('root'));
Or:
Note that the first argument has to be this.
Send "Goal" as a parameter to the shoot function:
class Football extends React.Component { shoot(a) { alert(a); } render() { return ( <button onClick={this.shoot.bind(this, "Goal")}>Take the shot!</button> ); }} ReactDOM.render(<Football />, document.getElementById('root'));
Note on the second example: If you send arguments without using the bind method, (this.shoot(this, "Goal") instead of this.shoot.bind(this, "Goal")), the shoot function will be executed when the page is loaded instead of waiting for the button to be clicked.
Event handlers have access to the React event that triggered the function.
In our example the event is the "click" event. Notice that once again the syntax is different when using arrow functions or not.
With the arrow function you have to send the event argument manually:
Arrow Function: Sending the event object manually:
class Football extends React.Component { shoot = (a, b) => { alert(b.type); /* 'b' represents the React event that triggered the function, in this case the 'click' event */ } render() { return ( <button onClick={(ev) => this.shoot("Goal", ev)}>Take the shot!</button> ); }} ReactDOM.render(<Football />, document.getElementById('root'));
Without arrow function, the React event object is sent automatically as the last argument when using the bind() method:
With the bind() method, the event object is sent as the last argument:
class Football extends React.Component { shoot = (a, b) => { alert(b.type); /* 'b' represents the React event that triggered the function, in this case the 'click' event */ } render() { return ( <button onClick={this.shoot.bind(this, "Goal")}>Take the shot!</button> ); }} ReactDOM.render(<Football />, document.getElementById('root'));
Just like in HTML, React uses forms to allow users to interact with the web page.
You add a form with React like any other element:
Add a form that allows users to enter their name:
class MyForm extends React.Component { render() { return ( <form> <h1>Hello</h1> <p>Enter your name:</p> <input type="text" /> </form> ); }}ReactDOM.render(<MyForm />, document.getElementById('root'));
Handling forms is about how you handle the data when it changes value or gets submitted.
In HTML, form data is usually handled by the DOM.
In React, form data is usually handled by the components.
When the data is handled by the components, all the data is stored in the component state.
You can control changes by adding event handlers in the onChange attribute:
Add an event handler in the onChange attribute, and let the event handler update the state object:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '' }; } myChangeHandler = (event) => { this.setState({username: event.target.value}); } render() { return ( <form> <h1>Hello {this.state.username}</h1> <p>Enter your name:</p> <input type='text' onChange={this.myChangeHandler} /> </form> ); }} ReactDOM.render(<MyForm />, document.getElementById('root'));
Note: You must initialize the state in the constructor method before you can use it.
Note: You get access to the field value by using the event.target.value syntax.
If you do not want to display the h1 element until the user has done any input, you can add an if statement.
Look at the example below and note the following:
Display the header only if username is defined:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '' }; } myChangeHandler = (event) => { this.setState({username: event.target.value}); } render() { let header = ''; if (this.state.username) { header = <h1>Hello {this.state.username}</h1>; } else { header = ''; } return ( <form> {header} <p>Enter your name:</p> <input type='text' onChange={this.myChangeHandler} /> </form> ); }} ReactDOM.render(<MyForm />, document.getElementById('root'));
You can control the submit action by adding an event handler in the onSubmit attribute:
Add a submit button and an event handler in the onSubmit attribute:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '' }; } mySubmitHandler = (event) => { event.preventDefault(); alert("You are submitting " + this.state.username); } myChangeHandler = (event) => { this.setState({username: event.target.value}); } render() { return ( <form onSubmit={this.mySubmitHandler}> <h1>Hello {this.state.username}</h1> <p>Enter your name, and submit:</p> <input type='text' onChange={this.myChangeHandler} /> <input type='submit' /> </form> ); }} ReactDOM.render(<MyForm />, document.getElementById('root'));
Note that we use event.preventDefault() to prevent the form from actually being submitted.
You can control the values of more than one input field by adding a name attribute to each element.
When you initialize the state in the constructor, use the field names.
To access the fields in the event handler use the event.target.name and event.target.value syntax.
To update the state in the this.setState method, use square brackets [bracket notation] around the property name.
Write a form with two input fields:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '', age: null, }; } myChangeHandler = (event) => { let nam = event.target.name; let val = event.target.value; this.setState({[nam]: val}); } render() { return ( <form> <h1>Hello {this.state.username} {this.state.age}</h1> <p>Enter your name:</p> <input type='text' name='username' onChange={this.myChangeHandler} /> <p>Enter your age:</p> <input type='text' name='age' onChange={this.myChangeHandler} /> </form> ); }} ReactDOM.render(<MyForm />, document.getElementById('root'));