Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

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,598 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,664 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