-1

Below code returns an error for me Uncaught (in promise) TypeError: Cannot read property 'setState' of undefined

I am new to react and this seems very basic. Any suggestion what could I be doing wrong. From the json result I want to store all names in my array.

import React, { Component } from "react";

class Search extends Component {
  constructor(props) {
  super(props);
  this.state = {
    list: [],
  }
}

Search() {

  fetch("http://url/getSearchResults")
    .then(res => res.json())
    .then(
      (res) => {

        this.setState({
          list: res.data.name
     })
  })
}

Toby
  • 12,743
  • 8
  • 43
  • 75
kimi86
  • 210
  • 4
  • 12
  • 2
    seems like an issue with `this` can you show where `Search` is called? – Chaim Friedman Jan 13 '20 at 21:37
  • declare search as an arrow function: `search = () => { ... }`. See [here](https://stackoverflow.com/questions/42556083/what-does-bindthis-in-constructor-do-in-reactjs) for more info. – Toby Jan 13 '20 at 21:38
  • Just noticed your class and method are called the same thing - I'd strongly recommend keeping method names unique from the component name. – Toby Jan 13 '20 at 22:01
  • 1
    Does this answer your question? [React this is undefined](https://stackoverflow.com/questions/38238512/react-this-is-undefined) – Dan O Jan 13 '20 at 22:04
  • there are many, many questions on Stack Overflow regarding `this` being undefined inside a Promise's `then` method. which of them did you research and why specifically did they not solve your issue? – Dan O Jan 13 '20 at 22:06

2 Answers2

1

This is a very common problem with classes in React - there are two ways to solve this problem:

  1. Bind your methods in the constructor:
constructor(props) {
  super(props);

  this.state = {
    list: [],
  }

  this.Search = this.Search.bind(this);
}
  1. Use an arrow function instead:
search = () => { ... }

See this post for more information.

Note: using componentDidMount() will be useful if you are trying to make the fetch call on mount - the answer above addresses the issue of this being undefined as per the error you are seeing.

Toby
  • 12,743
  • 8
  • 43
  • 75
  • 1
    What you're describing isn't necessary when using ECMAScript 2015 classes. Prototype methods have access to `this` if they're defined with the class body. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) That said, the formatting you did greatly clarified that what the OP was trying to do was nonsensical and my answer was wrong. – Chris Thompson Jan 13 '20 at 22:15
  • @ChrisThompson OP seems to have disappeared so perhaps we'll never know - however my post is in reference to [this](https://codepen.io/gaearon/pen/xEmzGg?editors=0010) - if you comment out the binding in the constructor, you can see the same error OP saw when the function is called. Either way there's lots of confusion to go around.. lol. – Toby Jan 14 '20 at 13:44
  • 1
    Isn't JavaScript great?! Yep, that link makes sense. The reason for that is that they then later pass it just as a function (rather than supplying an arrow function that then calls the function). If they were going to call with like`() => this.handleClick()` it wouldn't be necessary. But you're right, in the nonbinding case, you get the exact same error. – Chris Thompson Jan 14 '20 at 17:21
0

Add componentDidMount() to Search(), it is invoked immediately after a component is mounted (inserted into the tree). Initialization that requires DOM nodes should go here.Its a good place to load data from a remote endpoint.

G.Mestanza
  • 41
  • 7