IlariM
IlariM

Reputation: 376

ReactJS - setState Axios POST response

I'm trying to set a state for my Axios POST response but the array where I map the data is still empty. The data fetching is working good, but I just need to move all the data with the 'subject' keywords to my Todos array and print them out.

Here is my code so far;

App.js

import React, { Component } from 'react';
import axios from 'axios';
import Todos from "./Components/Todos"

class App extends Component {
  constructor(){
    super();
    this.state = {
      todos:[]
    }
  }

  // AXIOS request
  getTodos(){
    var postData = {
      "startDate": "startDate",
      "endDate": "endDate",
      "studentGroup": ["ID"]
    };
    let axiosConfig = {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': "Basic " + btoa("username" + ":" + "password")
      }
    };
    axios.post('url', postData, axiosConfig)
    .then((data) => {
      console.log(data);
      this.setState({todos: data.reservations ? data.reservations : []}, function(){
        console.log(this.state);
      })
    })
    .catch((err) => {
      console.log("Error: ", err);
    })
  }

  componentWillMount(){
    this.getTodos();
  }
  componentDidMount(){
    this.getTodos();
  }

  render() {
    return (
      <div className="App">
        <Todos todos={this.state.todos}/>
      </div>
    );
  }
}
export default App;

Todos.js

import React, { Component } from 'react';
import TodoItem from './TodoItem';

class Todos extends Component {
  render() {
    let todoItems;
    if(this.props.todos){
      todoItems = this.props.todos.map(todo => {
        return (
          <TodoItem key={todo.subject} todo={todo} />
        );
      });
    }
    return (
      <div className="Todos">
        <h3>Results:</h3>
          {todoItems}
      </div>
    );
  }
}
export default Todos;

TodoItem.js

import React, { Component } from 'react';

class TodoItem extends Component {
  render() {
    return (
      <li className="Todo">
        <strong>{this.props.todo.subject}</strong>
      </li>
    );
  }
}
export default TodoItem;

Snippet from console before setState:

enter image description here

Should I use some other function instead of an arrow function?

Upvotes: 2

Views: 6272

Answers (3)

Abdoul Dia
Abdoul Dia

Reputation: 106

I was having hard time with the "this" undefined. I solved it like this (calling function should be arrow function):

 handleGenerateCharge =(event) => {
        const header = new Headers();
        header.append('Access-Control-Allow-Origin', '*');  

        var charge = {
            name: "ABC",
            createDate: Moment(Date.now()).format()
        }

        axios.post("http://url", charge, header)
            .then((res) => {
                if (res.status === 200) {
                    this.update();
                }
            }).catch((error) => {
                this.setState({ errorMessage: error });
            })
        event.preventDefault();
    }

Upvotes: 0

Tomasz Mularczyk
Tomasz Mularczyk

Reputation: 36219

if you don't get this.setState is undefined error then it's a bit strange. Could you fix/copy the code below and verify if that helps:

import React, { Component } from 'react';
import axios from 'axios';
import Todos from "./Components/Todos"

class App extends Component {
  constructor(props){
    super(props);    // pass props to "father" constructor
    this.state = {
      todos:[]
    }
    this.getTodos = this.getTodos.bind(this);
  }

// AXIOS request
getTodos(){
  var postData = {
    "startDate": "startDate",
    "endDate": "endDate",
    "studentGroup": ["ID"]
  };
  let axiosConfig = {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': "Basic " + btoa("username" + ":" + "password")
    }
  };
  axios.post('url', postData, axiosConfig)
  .then((response) => {
    if(response.data.reservations) {
      this.setState({todos: response.data.reservations})
    }
  })
  .catch((err) => {
    console.log("Error: ", err);
  })
}

  componentDidMount(){
    this.getTodos();
  }

  render() {
    console.log(this.state.todos);
    return (
      <div className="App">
        <Todos todos={this.state.todos}/>
      </div>
    );
  }
}
export default App;

Now observe if console.log(this.state.todos); is called after the request is finished. If so, verify it's an empty array.

Upvotes: 1

Rachit Solanki
Rachit Solanki

Reputation: 379

Create self reference in function

getTodos(){
    var self = this; // create a this reference
    var postData = { .. };
    let axiosConfig = {... };
    axios.post(..)
        .then((data) => {
             self.setState('your updated state')
           }) 
        .catch((err) => {});

}

Upvotes: 0

Related Questions