1

Having a response issue.

When making an ajax call to retrieve data from the backend i retrieve the data, but it appears that it retrieves the data only if its wrapped in a .then(). Outside of a .then() then the data clears out.

consume is a personal module that handles axios calls.

here is the issue

componentWillMount() {
    const retrieveLogs = {
      method: "GET",
      url: this.state.url, 
    }
    consume.fetch(retrieveLogs)
      .then(res => {
        if(typeof res.logger === "object"){
          this.setState({
            logs: res.logger,

         })
         console.log(this.state.logs) // show the console log here but
        }
    })
    console.log(this.state.logs) // but shows empty array here why is this ?
  }
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
BARNOWL
  • 3,326
  • 10
  • 44
  • 80
  • I think it's running the second console.log before state is finished setting. – stever Jul 04 '19 at 18:51
  • i think so too, this issue would not be good if i was mapping the data to a list. So whats will be the best approach ? – BARNOWL Jul 04 '19 at 18:52
  • Can you put the .map logic as a callback to the promise res? – stever Jul 04 '19 at 18:54
  • can you provide an answer demonstrating what you mean by that. im sorry – BARNOWL Jul 04 '19 at 18:55
  • So you're using `consume` that depends on `axios` to make a fetch? Why not simply use the native [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)? – Nino Filiu Jul 04 '19 at 19:15
  • i figured it out thanks. – BARNOWL Jul 04 '19 at 19:16
  • Possible duplicate of [Why calling react setState method doesn't mutate the state immediately?](https://stackoverflow.com/questions/30782948/why-calling-react-setstate-method-doesnt-mutate-the-state-immediately) – Emile Bergeron Jul 04 '19 at 19:26
  • @NinoFiliu that's completely irrelevant here. – Emile Bergeron Jul 04 '19 at 19:28
  • @BARNOWL it looks like you're confused because of the async nature of JS, on top of the async nature of `setState`. In addition to the confusion caused by the [lazy evaluation of the console](https://stackoverflow.com/a/17547032/1218980) which makes it looks like it's there, but really wasn't when executed initially. – Emile Bergeron Jul 04 '19 at 19:32
  • And the reason why the last log is empty: https://stackoverflow.com/q/14220321/1218980 – Emile Bergeron Jul 04 '19 at 19:37

2 Answers2

2

componentWillMount is UNSAFE and deprecated, you should not use it, see details here. The best approach to is to use componentDidMount to fetch your data and then update the state. The initial render with an empty state is pattern, and you should not worry about it. Also you should not log your state like that, remember, setState is assynchronous and you have no guarantees that the state will be updated when calling console.log, in this cases use the second argument of setState which provides you a callback that only get's fired when all updates are finished.

componentDidMount() {
const retrieveLogs = {
  method: "GET",
  url: this.state.url, 
}
consume.fetch(retrieveLogs)
  .then(res => {
    if(typeof res.logger === "object"){
      this.setState({
        logs: res.logger,

     }, console.log(this.state.logs))

    }
})}

If you need to perform some operation after data arrive, use componentDidUpdate to implement your custom logic whenever props or state changes.

componentDidUpdate(prevProps, prevState){
   if(prevProps.item !== this.props.item)
       this.setState({item}, console.log(this.state.item))
}
Dupocas
  • 20,285
  • 6
  • 38
  • 56
0

Found a solution.

I can use componentDidUpdate, so that way when its completely done rendering in componentDidupdate i can then render the response data.

So if show === false, hence if state is rendered. then i show data, if not render null.

here is what i came up with.

 componentDidUpdate(prevProps){
    if(this.state.logs.length !== 0 && prevProps.logs === null){
      this.setState({
        show:false 
      })
    }
    console.log(this.state.logs); // shows here
  }


return(
  {!this.state.show ? (  
     <Logs logs= {this.state.logs} />  // renders the data.
  ):(
     null
   )}
)
BARNOWL
  • 3,326
  • 10
  • 44
  • 80