0

I tried adding a search field to search for planets. Can someone help me to fix this please?

The error I get is this: TypeError: Cannot read property 'state' of undefined handleChange C:/Users/charl/Desktop/IRONHACK/Paperbox/paperbox/src/pages/Home.js:29 26 | } 27 | 28 | handleChange(e){ // eslint-disable-next-line

29 | const planetssearchlist = this.state.planets.filter(planet => { | ^ 30 | if(planet.name){ 31 | if(planet.name.toLowerCase().includes(e.target.value.toLowerCase())){ 32 | return true


import React, { PureComponent } from 'react'
import axios from "axios";

class Home extends PureComponent {
    constructor(props) {
        super(props)

        this.state = {
            planets: []
        }
    }

    componentDidMount(){
        axios({
            method: "GET",
            url: "https://swapi.dev/api/planets/"
        })
        .then(response => {
            console.log(response)
            let planetslist = response.data.results;
            this.setState({planets: planetslist})
        })
        .catch(error => {
            console.log("You've made an error with the planets load charles: ",error)
        })
    }

    handleChange(e){ // eslint-disable-next-line
        const planetssearchlist = this.state.planets.filter(planet => {
             if(planet.name){
                if(planet.name.toLowerCase().includes(e.target.value.toLowerCase())){
                    return true 
                }   
            }
            this.setState({
                planets:planetssearchlist
            })
        })
    }

    render() {
        return (

        <div>
            <h1>Star Wars Planets</h1>

            <form>
                <input placeholder="searchbar" type="text" onChange={this.handleChange}></input>
            </form>

            {
                this.state.planets.map((planet,i) => (
                        <p key={i}>{planet.name}</p>
                ))   
            }

        </div>    

        )
    }
}

export default Home
  • Does this answer your question? [React this.state is undefined?](https://stackoverflow.com/questions/45998744/react-this-state-is-undefined) – shkaper Jun 01 '20 at 23:24

4 Answers4

1

You must bind the function to component, you can use lambda function syntax to define your method:

handleChange = (e) => {}

or in constructor:

this.handleChange = this.handleChange.bind(this)

Also your handleChange function is not working properly. You need to setState outside of the filter function. You can find working sample here: https://codesandbox.io/s/jovial-stallman-fs012?file=/src/index.js


Further things to do:

You are directly editing planet array in handleChange function. When user searches string you are removing items from state.planets. So when user removes search string, old planets will not be showing because of the removal.

  • You need to store planets in a immutable array.
  • After you did the search filter immutable array to create presentation array.
  • Display presentation array in render function.

Also i highly recommend to checkout the documentation for Passing Functions to Components:https://reactjs.org/docs/faq-functions.html

Doruk Eren Aktaş
  • 2,121
  • 8
  • 23
  • ok thanks! ReferenceError: Cannot access 'planetssearchlist' before initialization is my error now! anyone that knows why? – Charlinhovdb Jun 01 '20 at 23:54
  • Did you look at the code in the link: https://codesandbox.io/s/jovial-stallman-fs012?file=/src/index.js. If you did already can you update the code in your question? – Doruk Eren Aktaş Jun 01 '20 at 23:56
0

Try using an arrow function for handleChange method like this:

handleChange = (e) => {

}
  • ok thanks! ReferenceError: Cannot access 'planetssearchlist' before initialization is my error now! anyone that knows why? – Charlinhovdb Jun 01 '20 at 23:54
0

You should bind handleChange method in constructor like :

this.handleChnage = this.handleChange.bind(this)

        or 

you should use arrow function

handleChange = (e) => { }

  • ok thanks! ReferenceError: Cannot access 'planetssearchlist' before initialization is my error now! anyone that knows why? – Charlinhovdb Jun 01 '20 at 23:54
0

It is related to closure and this keyword in javascript, you define handleChange in Home component but you pass it as a callback for onClick, it is actually not called in Home ==> this is not context of Home any more. There is 4 way you can solve this. Using arrow function to define the function (I like this way):

handleChange = (event) => {}

Using array function in render:

// other code
<form>
   <input placeholder="searchbar" type="text" onChange={(event) => this.handleChange(event)}></input>
</form>
// other code

Bind the function in constructor

// Other code
constructor(props) {
        super(props)

        this.state = {
            planets: []
        }
        this.handleChange = this.handleChange.bind(this)
    }
// Other code

Binding function in render:

// other code
<form>
   <input placeholder="searchbar" type="text" onChange={this.handleChange(this)}></input>
</form>
// other code

Actually there is one more way that using React.createClass, but I'll not mentioned here because it is not JSX way.

ReferenceError: Cannot access 'planetssearchlist' before initialization: Because you are using it inside of this.state.planets.filter where the planetssearchlist have not done initialised yet , bring it outside

handleChange(e){ // eslint-disable-next-line
    const planetssearchlist = this.state.planets.filter(planet => {
         if(planet.name){
            if(planet.name.toLowerCase().includes(e.target.value.toLowerCase())){
                return true 
            }   
        }})
    // This is need to be outside of this.state.planets.filter
    this.setState({
      planets:planetssearchlist
    })
  }
Tony Nguyen
  • 3,298
  • 11
  • 19
  • ok thanks! ReferenceError: Cannot access 'planetssearchlist' before initialization is my error now! anyone that knows why? – Charlinhovdb Jun 01 '20 at 23:54
  • Because you are using it inside of `this.state.planets.filter` where the `planetssearchlist` have not done initialised yet , bring it outside. Please check my updated answer – Tony Nguyen Jun 02 '20 at 00:00