0

Creating dummy website with a few functional aspects. Just to clarify, I started learning React a week ago so please be kind with your answers. Thank you!

Initially created a state in App.js that allows me to add and delete clients. (like the corny to-do list)

Now using a different component where I can 'add a lesson' I want to have a dropdown selector where I can choose one of the existing clients from the other state as my option. I have created everything so far that takes the inputs and console.log() is showing that everything is going through fine. However, I can't seem to get the dropdown options to show as the existing clients so I can add the lesson in a different state. To clarify I have 2 states, clients and lessons(with the existing clients).

Here is my App.js

import React, { Component } from 'react'
import Clients from './components/Clients'
import AddClient from './components/AddClient'
import NavBar from './components/NavBar'
import AddLesson from './components/AddLesson'

    class App extends Component {
      state = {
        clients : [
          {id : 1 , name : 'bob', price : 30},
          {id : 2 , name : 'mary', price : 40},
          {id : 3 , name : 'greg', price : 45}
        ],
        lessons : [
          {id: null, name: '', time: null}
        ]
      }

      deleteClient = (id) => {
        let clients = this.state.clients.filter(client => {
          return client.id !== id
        })
        this.setState({
          clients: clients
        })
      }

      addClient = (newClient) => {
        newClient.id = Math.random();
        let clients = [...this.state.clients, newClient];
        clients.sort((a, b) => a.name.localeCompare(b.name))
        this.setState({
            clients: clients,
        })
      }

      addLesson = (newLesson) => {
        newLesson.id = Math.random(); 
        let lessons = [...this.state.lessons, newLesson];
        this.setState({
            lessons: lessons,
        })
        console.log(lessons)
      }

      render() {
        return (
          <div className="App">
            <NavBar/>
            <Clients clients={this.state.clients} deleteClient={this.deleteClient}/>
            <AddClient addClient={this.addClient}/>
            <AddLesson addLesson={this.addLesson}/>
          </div>
        );
      }
    }

    export default App;

Here is AddLesson.js

import React, {Component} from 'react'

class AddLesson extends Component {
    state = {
        lessons: [
            {id : null, name: '', time: null}
        ]
    }

    handleChange = (e) => {
        this.setState({
            [e.target.id] : e.target.value
        })
    } 

    handleSubmit = (e) => {
        e.preventDefault();
        this.props.addLesson(this.state);
        e.target.reset();
    }

    render() {
        return (
            <div className="text-center">
                <h2>Add a lesson</h2>
                <form onSubmit={this.handleSubmit}>

                    <select name="lesson_client">
                        <option>{this.props.clients}</option>
                    </select>

                    {/* <label htmlFor="name">Client Name: </label>
                    <input type="text" id="name" onChange={this.handleChange}/><br/>
                    <label htmlFor="time">Lesson Duration (in hours): </label>
                    <input type="text" id="time" onChange={this.handleChange}/><br/>
                    <button className="btn btn-primary">Add Client</button> */}
                </form>
            </div>
        )
    }
}

export default AddLesson

I tried not to overload with code, so if I am missing something, please let me know and I will edit it.

5
  • I also have a Clients.js that actually renders out to the user the list of Clients. If that is needed I can also post that. Commented Mar 6, 2019 at 10:04
  • Sorry, to understand, are you trying to render the client list inside the AddLesson component? If so, your not passing the clients through as a prop. Commented Mar 6, 2019 at 10:08
  • You are looking for: reactjs.org/docs/lists-and-keys.html Commented Mar 6, 2019 at 10:09
  • @Kurtis yes, I want the client list to show up as the options in the dropdown list. I thought that because the AddLesson.js is a class based component, the props get passed down automatically? Commented Mar 6, 2019 at 10:12
  • Only the React stuff gets passed down automatically. You need to do two things. Firstly add ` <AddLesson addLesson={this.addLesson} clients={this.state.clients} />` to App.js. Secondly you need to map over the clients like Avanthika has answered below. Commented Mar 6, 2019 at 10:15

1 Answer 1

1

You need to loop over clients & render them.

<select onChange={(e) => this.handleChange(e)} name="lesson_client">
  {this.props.clients.map(client => <option key={client.id} value={client.price}>{client.name}</option>)}
</select>

You can listen to handleChange to read the selected value. (Note: I have changed e.target.id to e.target.name since there is no id attr on select tag)

handleChange = (e) => {
  this.setState({
    [e.target.name] : e.target.value
  })
} 

And I also noticed you are not passing clients to AddLesson component. Please pass it for the code to work.

<AddLesson clients={this.state.clients} addLesson={this.addLesson}/>

Sign up to request clarification or add additional context in comments.

4 Comments

He's not using that handleChange function for the dropdown. That is used in the text fields that are commented out so changing id would break those. Nice edits after my comment above :-)
Umm ya, just noticed the commented code, he can reuse handleChange with name attribute!
question: where in <select></select> is the [e.target.name] ?
The attr name="lesson_client" should do the trick for you! <select name="lesson_client"></select>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.