1

I want to store the value obtained after the api call in the state so that it can be rendered later on.I want the search term to be fetched from the api,i tried to use compontdidMount and conditionally fetch from the api but it didn't work as well.please help

import React, { Component } from 'react'
import axios from 'axios';
class New extends Component {
    state = {
        term:'',
        res:[]
      }
      handleChange = e => {
        this.setState({ term: e.target.value });
      };
      handleSubmit = e => {
        e.preventDefault();
        var url = `https://icanhazdadjoke.com/search?term=${this.state.term}`;
  var options = { 
    method: 'GET',
    headers: {
      "Accept" : "application/json" 
    }
  };
  axios.get(url,options)
        .then(response =>
          this.setState({res:[response.data.results]})
         
        )
        .catch(error => {
          // error.message is the error message
        })
        console.log(this.state)
      };
    render() { 
        return (<form className="jokes" onSubmit={this.handleSubmit}>
        <input
          onChange={this.handleChange}
          value={this.state.title}
          type="text"
          name="term"
          required
          placeholder="cemetery"
        />
        <button type="submit"  value="Search" >Search</button>
        
      </form>  );
    }
}
 
export default New;
Shivam_Yadav
  • 206
  • 2
  • 17

2 Answers2

2

Working demo, provided that you search a joke term that exists.

Just two observations:

  1. Setting the state like this this.setState({res:[response.data.results]}) will make the response be inside an array with only the zeroth element. But response.data.results is already an array, so just save this.setState({res:response.data.results})
  2. this.setState does not take effect right away and logging in the next line won't work. The state change is queued and async... you are asking React to update when it can.

EDIT:

setState has a secondary and optional callback argument, that executes after the actual update:

this.setState({ res: [response.data.results] }, () => {
  console.log(this.state.res);
})
Rodrigo Amaral
  • 1,324
  • 1
  • 13
  • 17
  • ..Thanks..Will the use async await help me avoid these kind of errors? – Shivam_Yadav Jul 19 '20 at 04:29
  • I updated my answer. You can also always log the props/state in the render method for debugging purposes or, even better, use React Dev Tools to check it. – Rodrigo Amaral Jul 19 '20 at 04:31
  • thanks..once again..I was using redux and react Dev tools but i messed up the code midway so i thought using local state instead of store would save some time but it backfired..thank you for this valuable info : ) – Shivam_Yadav Jul 19 '20 at 04:36
  • You welcome. BTW, for the record console.log might as well be async in the behaviour. I've noticed it's unreliable in some cases, don't count on it. – Rodrigo Amaral Jul 19 '20 at 04:38
  • : | won't use console.log anymore – Shivam_Yadav Jul 19 '20 at 04:43
  • Console logging is still the fastest way to quickly debug simple issues, with occasional "race conditions" in rare cases https://stackoverflow.com/q/23392111/6281832 . But don't let it make you forget about Devtools. – Rodrigo Amaral Jul 19 '20 at 04:49
1

It appears as though the state does get updated correctly. Check out this sandbox where I demo your code and render the API results.

Robert Cooper
  • 2,160
  • 1
  • 9
  • 22
  • 3
    @CosmicCallisto I've updated the answer. Everything seems OK to me. I think you add your `console.log` statement in the wrong place which gave you the false impression that state was not being updated. – Robert Cooper Jul 19 '20 at 04:08
  • I spent 8 hours on this : ( .Nobody told me this also happens...Thank You so much .. : ) – Shivam_Yadav Jul 19 '20 at 04:15