Skip to main content

React Forms Review

Set Up Inputs in a Form#

Let's add our inputs to state

App.js
this.state = {  playlist: playlist,  title: "",  artist: "",  time: "0:00",};

Let's add value to all three input fields

App.js
<form>  <label htmlFor="song">    Song    <input type="text" id="song" value={this.state.title} />  </label>  <label htmlFor="artist">    Artist    <input type="text" id="artist" value={this.state.artist} />  </label>  <label htmlFor="time">    Time    <input type="text" id="time" value={this.state.time} />  </label></form>

Now when we type in the input fields, they won't change.

Let's handle the input

App.js
handleChange(event) {  this.setState({ [event.target.id]: event.target.value });}

Don't forget to bind it in the constructor

Add the event listener

App.js
<label htmlFor="song">  Song  <input    type="text"    id="song"    value={this.state.title}    onChange={this.handleChange}  /></label><label htmlFor="artist">  Artist  <input    type="text"    id="artist"    value={this.state.artist}    onChange={this.handleChange}  /></label><label htmlFor="time">  Time  <input    type="text"    id="time"    value={this.state.time}    onChange={this.handleChange}  /></label>

Get Submit functionality Working#

Write our submit function (and don't forget to bind it in the constructor) (and don't forget to add onSubmit={this.handleSubmit} to your form tag)

Remember, submit's default behavior is to refresh the page. Let's be sure to prevent that default.

We should not ever mutate state directly. We must update state with this.setState()

First, we're going to create a new object with our state we collected from our inputs.

Then we are going to make a new array, using the destructuring spread operator so that we don't alter state outside of setState.

Finally, inside of setState, we'll update our songs array to our new array

App.js
handleSubmit(event) {  event.preventDefault();  const newSong = {    title: this.state.title,    artist: this.state.artist,    time: this.state.time,  };
  const updatedSongs = [...this.state.playlists.songs, newSong];
  this.setState({    playlists: updatedSongs,    name: "",    artist: "",    time: "0:00",  });}

It would be nice to clear the fields. We can do this by updating state a bit more

App.js
this.setState({  playlist: updatedPlaylist,  title: "",  artist: "",  time: "0:00",});

Bonus: Can you figure out how you would delete a song?

Your final App.js should look something like this:

App.js
import React, { Component } from "react";import Footer from "./components/Footer";import Header from "./components/Header";import playlist from "./data.js";
class App extends Component {  constructor(props) {    super(props);    this.state = {      playlist: playlist,      title: "",      artist: "",      time: "0:00",    };    this.handleChange = this.handleChange.bind(this);    this.handleSubmit = this.handleSubmit.bind(this);  }  handleChange(event) {    this.setState({ [event.target.id]: event.target.value });  }  handleSubmit(event) {    event.preventDefault();
    const newSong = {      title: this.state.title,      artist: this.state.artist,      time: this.state.time,    };    console.log(newSong);    const updatedPlaylist = [newSong, ...this.state.playlist];
    this.setState({      playlist: updatedPlaylist,      title: "",      artist: "",      time: "0:00",    });  }  render() {    return (      <div>        <Header />        <form onSubmit={this.handleSubmit}>          <label htmlFor="title">            Song            <input              type="text"              id="title"              value={this.state.title}              onChange={this.handleChange}            />          </label>          <label htmlFor="artist">            Artist            <input              type="text"              id="artist"              value={this.state.artist}              onChange={this.handleChange}            />          </label>          <label htmlFor="time">            Time            <input              type="text"              id="time"              value={this.state.time}              onChange={this.handleChange}            />          </label>          <label>            <input type="submit" />          </label>        </form>        <main>          <div>            <h3>Playlist 1</h3>            <table>              <thead>                <tr>                  <th>Song</th>                  <th>Arist</th>                  <th>Time</th>                </tr>              </thead>              <tbody>                {this.state.playlist.map((song, index) => {                  return (                    <tr key={index}>                      <td>{song.title}</td>                      <td>{song.artist}</td>                      <td>{song.time}</td>                    </tr>                  );                })}              </tbody>            </table>          </div>        </main>        <Footer />      </div>    );  }}
export default App;