Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript React by Example Building the Application Removing Names From the List

After adding the remove, all my guests disappeared

I followed every step, replayed the video and still can't see where our code is differing.

App.jsx
import React, { Component } from 'react';
import './App.css';
import GuestList from './GuestList'

class App extends Component {

  state = {
    isFiltered: false,

    pendingGuest: "",

    guests: [
      {
        name: 'Rapha',
        isConfirmed: false,
        isEditing: false
      },
      {
        name: 'Filipe',
        isConfirmed: true,
        isEditing: false
      },
      {
        name: 'Eloi',
        isConfirmed: true,
        isEditing: true
      }
    ]
  }

  toggleGuestPropertyAt = (property,indexToChange) => {
    this.setState({
      guests: this.state.guests.map((guest, index) =>{
        if (index === indexToChange) {
          return {
            ...guest,
            [property]: !guest[property]
          };
        }
        return guest;
      })
    })
  }

  toggleConfirmationAt = index => {
    this.toggleGuestPropertyAt("isConfirmed", index);
  }

  removeGuestAt = index => {
    this.setState({
      guests: [
        ...this.state.guests.slice(0, index),
        ...this.state.guests.slice(index + 1)
      ]
    })
  }

  toggleEditingAt = index => {
    this.toggleGuestPropertyAt("isEditing", index);
  }

  setNameAt = (name, indexToChange) => {
    this.setState({
      guests: this.state.guests.map((guest, index) => {
        if (index === indexToChange) {
          return {
            ...guest,
            name
          };
        }
        return guest;
      })
    })
  }

  toggleFilter = () => {
    this.setState({isFiltered: !this.state.isFiltered })
  }

  handleNameInput = e => {
    this.setState({pendingGuest: e.target.value})
  }

  newGuestSubmitHandler = e => {
    e.preventDefault();
    this.setState({
      guests: [
        {
          name: this.state.pendingGuest,
          isConfirmed: false,
          isEditing: false
        },
        ...this.state.guests
      ],
      pendingGuest: ''
    })
  }

  getTotalInvited = () => this.state.guests.length;

  //getAttendingGuests = () =>
  //getUnconfirmedGuests = ()=>


  render() {
    return (
      <div className="App">
        <header>
          <h1>RSVP</h1>
          <p>A Treehouse App</p>
          <form onSubmit={this.newGuestSubmitHandler} >
            <input 
              type="text"
              onChange={this.handleNameInput} 
              value={this.state.pendingGuest} 
              placeholder="Invite Someone" />
              <button type="submit" name="submit" value="submit">Submit</button>
        </form>
      </header>
          <div className="main">
            <div>
              <h2>Invitees</h2>
              <label>
                <input type="checkbox"
                  onChange={this.toggleFilter}
                  checked={this.state.isFiltered} /> Hide those who haven't responded
          </label>
        </div>
              <table className="counter">
                <tbody>
                  <tr>
                    <td>Attending:</td>
                    <td>2</td>
                  </tr>
                  <tr>
                    <td>Unconfirmed:</td>
                    <td>1</td>
                  </tr>
                  <tr>
                    <td>Total:</td>
                    <td>3</td>
                  </tr>
                </tbody>
              </table>
              <GuestList
                guests={this.state.guests}
                toggleConfirmationAt={this.toggleConfirmationAt}
                toggleEditingAt={this.toggleEditingAt} 
                setNameAt={this.setNameAt}
                isFiltered={this.state.isFiltered}
                removeGuestAt={this.removeGuestAt}
              />
      </div>
    </div>
    );
  }
}

export default App;
GuestList.jsx
import React from 'react';
import PropTypes from 'prop-types';
import Guest from './Guest';


const GuestList = props => 
  <ul>
    {props.guests
      .filter(guest => !props.isFiltered || guest.isConfirmed )
      .map((guest, index) =>
        <Guest 
          key={index}
          name={guest.name} 
          isConfirmed={guest.isConfirmed}
          isEditing={guest.isEditing}
          handleConfirmation={() => props.toggleConfirmationAt(index)}
          handleToggleEditing={() => props.toggleEditingAt(index)} 
          setName={text => props.setNameAt(text, index)} 
          handleRemove={props.removeGuestAt(index)}/>

    )}
  </ul>



GuestList.propTypes = {
  guests: PropTypes.array.isRequired,
  toggleConfirmationAt: PropTypes.func.isRequired,
  toggleEditingAt: PropTypes.func.isRequired,
  setNameAt: PropTypes.func.isRequired,
  isFiltered: PropTypes.bool.isRequired,
  removeGuestAt: PropTypes.func.isRequired
}

export default GuestList;
Guest.jsx
import React from 'react';
import PropTypes from 'prop-types'
import GuestName from './GuestName';
const Guest = props =>
      <li>
        <GuestName 
          isEditing={props.isEditing} 
          handleNameEdits={e => props.setName(e.target.value)} >{props.name}</GuestName>
        <label>
          <input type="checkbox" 
            checked={props.isConfirmed}
            onChange={props.handleConfirmation} /> Confirmed
        </label>
        <button onClick={props.handleToggleEditing} >
      {props.isEditing ? "save" : "edit"}
        </button>
        <button onClick={props.handleRemove} >remove</button>
      </li>



Guest.propTypes = {
  name: PropTypes.string.isRequired,
  isConfirmed: PropTypes.bool.isRequired,
  isEditing: PropTypes.bool.isRequired,
  handleConfirmation: PropTypes.func.isRequired,
  handleToggleEditing: PropTypes.func.isRequired,
  setName: PropTypes.func.isRequired,
  handleRemove: PropTypes.func.isRequired
}

export default Guest;
Gari Merrifield
Gari Merrifield
9,558 Points

That is pretty much unreadable outside the code boxes.All the formatting is lost.

2 Answers

I think it's because when you try and pass index as an argument to the props.removeGuestAt function, it's in the first position, which I believe will always be treated as the event object. You will likely need to have another arrow function further down that first passes the event as the first argument and then the index as the second, and adjust your removeGuestAt function appropriately.

Look at how the name changing functions are set up, you'll see some extra functions with e as the argument. This is the event.

Sammy Kidan
Sammy Kidan
6,730 Points

could you show how this would be done please?

Boon Kiat Seah
Boon Kiat Seah
66,639 Points

handleRemove={props.removeGuestAt(index)}/>

I found your error. On GuestList.js, under the Guest component, the triggering of the function in prop.handleRemoval need to be written this way

handleRemove= { () => props.removeGuestAt(index)} />

Your way of writing will remove all guests upon page rendering resulting in your page always loaded with zero guest in the array. With the above rectification, the handleRemove function will only be triggered based on the button onClick event binded.

Hope this helps