Let's talk about how we set up our state. Remember that state is like a storage container for information within your component. Here we're setting up our state to be able to store the information we need to create a workout, result, description and def. Next, we need to create a way to change the state .
Step 2. Change State Based on Input
We need to create some functions to change our state based on user input. So when the user types, we want to capture that information and change our state based off of it. So the first thing we're going to do is create a function called handleChange. Check out the code below. Chances are you've seen this exact function before, we're just starting by capturing an event (in this case when the user types), and grabbing the name of the field, and the value they've typed in. Note that the name of our input must match the corresponding name in our state. I.E. in this example, the result needs to match result, etc.
Next, we want to be able to, when they click the button to run a POST request to create our workout. We need to create a function that can do this. Write the following code beneath your handleChange function.
Let's talk about what this function is doing. It's taking an event, in this case, the click of submitting in a form and preventing default, which in this case is the page reloading. Then we're doing fetch with a method of post.
Notice that in our body, we're using our state. This works because this is the format we've told the workout log back end to accept.
Also notice the "Authorization" field in our header, where we're passing our token from props. Remember that this token comes from our parent components, and we've just passed it down several times as a prop so that we can use it to make API requests.
Then we call .json() on the response, like normal, and then we're calling a function from our parent component called updateWorkoutsArray() which we know just calls a GET to get all the workouts.
Lastly, we're setting our state back to nothing, so that when we want to create a new workout, we'll be starting with a blank slate.
Step 4. Setting Up the Render
We want to create a form to capture user input and also call our submit function. We're going to be using ReactStrap for a lot of the things in our render. Type the following code then we'll discuss it:
<Form>, <Input>, <Button>, <FormGroup>, etc. are all from reactstrap
Notice how the input fields all have onChange set to this.handleChange, so that when a user types, this function is called and the state is updated. You can see this in action if you open up your React Dev Tools in your browser
Notice how on form onSubmit we're calling our handleSubmit function
Notice how the name on the inputs matches that in the state
Finished Code
import React, { Component } from'react';import { Button, Form, FormGroup, Label, Input } from'reactstrap';classWorkoutCreateextendsComponent {constructor(props) {super(props)this.state = { id:'', result:'', description:'', definition:'' }; }handleChange= (event) => {// try console.log(event) to see when this method will be invokedthis.setState({ [event.target.name]:event.target.value }) }handleSubmit= (event) => {event.preventDefault();fetch(`http://localhost:3000/api/log/`, { method:'POST', body:JSON.stringify({ log:this.state }), headers:newHeaders({'Content-Type':'application/json','Authorization':this.props.token }) }).then((res) =>res.json()).then((logData) => {// after we create a log we want to pull that data from the server.this.props.updateWorkoutsArray()this.setState({ id:'', result:'', description:'', definition:'' }) }) }render() {return ( <div> <h3>Log a Workout</h3> <hr /> {/* after the form is submitted the data gets sent to the method above*/} <FormonSubmit={this.handleSubmit} > <FormGroup> <Labelfor="result">Result</Label> <Input id="result" type="text" name="result" value={this.state.result} placeholder="enter result" onChange={this.handleChange} />
</FormGroup> <FormGroup> <Labelfor="def">Type</Label> <Input type="select" name="definition" id="definition" value={this.state.definition} onChange={this.handleChange} placeholder="Type">
<option></option> <optionvalue="Time">Time</option> <optionvalue="Weight">Weight</option> <optionvalue="Distance">Distance</option> </Input> </FormGroup> <FormGroup> <Labelfor="description">Notes</Label> <Input id="description" type="text" name="description" value={this.state.description} placeholder="enter description" onChange={this.handleChange} />
</FormGroup> <Buttontype="submit"color="primary"> Submit </Button> </Form></div> ) }}exportdefault WorkoutCreate;
Let's include this in the WorkoutIndex Component import section
import WorkoutCreate from'./WorkoutCreate';
then in the render let's add the component in lieu of the comment