Home > front end >  Cannot render data from REST API's GET (managed in Django) response in React
Cannot render data from REST API's GET (managed in Django) response in React

Time:12-06

I am having the issue of data not being rendered from API response in React even though I do receive it.

I have the following "Admin-Notification" component:

import React from "react";
import './Admin-notifications.css';
import axios from 'axios'; 


class AdminNotifications extends React.Component {
    constructor(){
        super();
        this.state = {
            events:[
                {
                    "id": 1,
                    "name": "Fotosinteza plantelor",
                    "start_date": 1637496120,
                    "end_date": 4098071460,
                    "location": "Cluj-Napoca",
                    "description": "Aduceti planta",
                    "status": "pending",
                    "id_organizer": 2,
                    "id_type": 1
                },
                {
                    "id": 2,
                    "name": "Cantecul greierilor de peste imas",
                    "start_date": 1637669280,
                    "end_date": 4098071460,
                    "location": "Imas",
                    "description": "In padurea cu alune aveau casa 2 pitici",
                    "status": "pending",
                    "id_organizer": 2,
                    "id_type": 1
                },
                {
                    "id": 4,
                    "name": "test",
                    "start_date": 1637518260,
                    "end_date": 4098071460,
                    "location": "test",
                    "description": "test",
                    "status": "pending",
                    "id_organizer": 2,
                    "id_type": 1
                }
            ]
        }
        this.state2={
            events:[],
        }
    }
    getEvents(){
        axios
            .get("http://127.0.0.1:8000/api/getevents")
            .then(response =>{
                this.state2.events = response.data;
            }) 
            .catch(err => console.log(err));
    };

    render(){
        this.getEvents();
        console.log(this.state);
        console.log(this.state2);
        const {events} = this.state2;
        return(
            <main className="mw6 center main">
                {
                    events.map((event)=>{
                      
                        return(
                            <article key={event.id} className="dt w-100 hight padd bb  pb2  component" href="#0">
                                <div className="col-md-3">
                                    <div className="dtc w2 w3-ns v-mid">
                                        {/* <img src={event.img} 
                                        alt="event image from organizator"
                                        className="ba b--black-10 db br-100 w2 w3-ns h2 h3-ns"/> */}
                                    </div>
                                    <div className="dtc v-mid pl3">
                                        <h1 className="f6 f5-ns fw6 lh-title black mv0">{event.name} </h1>
                                        <h2 className="f6 fw4 mt0 mb0 black-60">{event.description}</h2>
                                    </div>
                                    <div className="dtc v-mid">
                                        <form className="w-100 tr">
                                        <button className="btn" type="submit">Accept</button>
                                        </form>
                                    </div>
                                    <div className="dtc v-mid">
                                        <form className="w-100 tr">
                                        <button className="btn" type="submit">Decline</button>
                                        </form>
                                    </div>

                                </div>
                            </article>
                    )})
                }
            </main>
        )
    }
}

export default AdminNotifications;

There, you can see that I have two states: state and state2. "this.state" is a hard-coded variant of the data that is coming from the API and "this.state2" is the data that came from the API.

Here is a picture of the console.log() from the render(), where first 'events' belongs to "state" and second one belongs to "state2": enter image description here

Here is how the website looks like if we map using "state":

const {events} = this.state;
        return(
            <main className="mw6 center main">
                {
                    events.map((event)=>{
                    ...

Picture: enter image description here

This is fine, this is how I want the website to look like.

And here is how it looks like using the data from the API:

const {events} = this.state2;
        return(
            <main className="mw6 center main">
                {
                    events.map((event)=>{
                    ...

Picture: enter image description here

Here are the API calls:

enter image description here

I can also provide you with the backend code.

View of the API:

@api_view(['GET'])
def getevents(request):
    if request.method == "GET":
        events = Event.objects.all()
        serializer = EventSerializer(events, many=True)
        return Response(serializer.data)

Yes, I did take care that there are no overwrites. This is the only view for this path.

Here is the Serializer that I have used:

class EventSerializer(serializers.ModelSerializer):
    class Meta:
        model = Event
        fields = '__all__'

Here is the model of the "Event":

class Event(models.Model):
    name = models.TextField()
    id_organizer = models.ForeignKey(User, on_delete=CASCADE, db_column='id_organizer')
    start_date = models.BigIntegerField()
    end_date = models.BigIntegerField()
    location = models.TextField()
    description = models.TextField()
    id_type = models.ForeignKey(EventType, on_delete=CASCADE, db_column='id_type')
    status = models.CharField(max_length = 50)
    class Meta:
        db_table="events"

Here is the table's database from where I get the data:

enter image description here

I did a print before returning the data in Django. Here is the result:

@api_view(['GET'])
def getevents(request):
    if request.method == "GET":
        events = Event.objects.all()
        serializer = EventSerializer(events, many=True)
        print(serializer.data)
        return Response(serializer.data)

Picture enter image description here

As you may have noticed, the API got called twice. I cannot really explain why this is happening, but in order to confirm this, if I add a console.log() inside the function that calls the API, and I get the console.log() twice, meaning that the function does calls twice.

getEvents(){
        
        axios
            .get("http://127.0.0.1:8000/api/getevents")
            .then(response =>{
                this.state2.events = response.data;
                console.log("test1");
            }) 
            .catch(err => console.log(err));
    };

Picture:

enter image description here

I have no idea why it is being called twice. But I do suspect it is one of the problems.

And here are the URL paths:

urlpatterns = [
    path('api/login', views.login),
    path('api/addevent', views.addevent),
    path('api/getevents', views.getevents),
]

I have tried to use a Promise type, parsing in different ways the data and pushing it to "state2", returning the data into the render directly but nothing really worked.

CodePudding user response:

Solution found:

constructor(){
        super();
        this.state = {
            events:[]
        }
    }
    componentDidMount(){
        axios
        .get("http://127.0.0.1:8000/api/getevents")
        .then(response =>{
            this.setState({events: response.data});
        }) 
        .catch(err => console.log(err));
    }

To be honest, I have no idea why it wouldn't work the other way. But glad to have this problem solved.

CodePudding user response:

You cannot manipulate the state directly and have to use the this.setStae function to update it like below

getEvents(){
  axios
    .get("http://127.0.0.1:8000/api/getevents")
    .then(response =>{
      this.setState({events:response.data})
      console.log("test1");
    })
    .catch(err => console.log(err));
};
  • Related