django-react cannot fetch data properly - reactjs

models.py
class Book(models.Model):
name = models.CharField(max_length=100, unique=True)
author = models.CharField(max_length=64)
passcode = models.CharField(max_length=80)
serializers.py
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = '__all__'
views.py
class GetBooks(APIView):
def get(self, request):
books = models.Book.objects.all()
data = serializers.BookSerializer(books, many=True).data
return Response(data, status=status.HTTP_200_OK)
urls.py
urlpatterns = [
path('get-books', views.GetBooks.as_view(), name='get-books')
]
Main.js
import React, { Component } from 'react'
export default class Main extends Component {
constructor(props){
super(props)
this.state = {
books: ''
}
this.getBooks()
}
getBooks() {
fetch('http://127.0.0.1:8000/api/get-books') // go down to see the data
.then((response) => {
const books = response.json()
console.log(books) // go down to see the output <---- !!
this.setState({
books: books
})
})
}
render() {
return (
<div>
// for book in books show book.name, book.author ...
</div>
)
}
}
Books data from (http://localhost/api/get-books)
[
{
"id": 1,
"name": "book1",
"author": "author1",
"passcode": "123"
},
{
"id": 2,
"name": "book2",
"author": "auhthor2",
"passcode": "123"
}
]
console.log(data)
Promise { <state>: "pending" }
​
<state>: "fulfilled"
​
<value>: Array [ {…}, {…} ]
​​
0: Object { id: 1, name: "book1", author: "author1", … }
​​
1: Object { id: 2, name: "book2", author: "author2", … }
​​
length: 2
​​
<prototype>: Array []
I want to iterate through all the books and display it to the user, the fetched data return as an array but I cant access it from this.state.books (i just recently started using react and django so please have mercy...)

I FOUND A SOLUTION
Main.js
import axios from 'axios'
import React, { Component } from 'react'
import Books from './Books'
export default class Main extends Component {
constructor(props){
super(props)
this.state = {
books: []
}
}
componentDidMount() {
axios.get('http://localhost:8000/api/get-books')
.then(res => {
this.setState({
books: res.data
})
})
}
render() {
return (
<div>
<Books books={this.state.books} />
</div>
)
}
}
Books.js
import React from 'react'
const Books = ({books}) => {
return (
<div>
{books.map(book => (
<div>
<h1>{book.name}</h1>
<small>{book.author}</small>
</div>
))}
</div>
)
}
export default Books
I simply used axios, put the data in an array and sent it to Book.js, then used the .map() to iterate through them!

Related

Unable to display array of only one object using reactjs

My Objective is to display the name which is inside the object. here is the snippet attached for your reference.
it contains:
{
id: "12497wewrf5144",
name: "ABC",
isVisible: "false"
}
I have tried in this way:
import React, { Component } from "react";
class Demo extends Component {
constructor(props: Props) {
super(props);
this.state = {
demo: {}
};
}
componentDidMount() {
axios.get('/api/random')
.then(res => {
this.setState({demo: res.data})
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<div>
<h1>{this.state.demo.name}</h1>
</div>
);
}
}
export default Demo;
But i'm not getting the value of name.
We use map for multiple objects in array, but do we need to map even for single array?
i have tried giving like "this.state.demo[0].name", but this one also not working
Can anyone help me in this query?
Assuming your API response is like following
data =[
{id: "12497wewrf5144", name: "ABC", isVisible: "false"},
{id: "12497wewrf5255", name: "CBD", isVisible: "true"}
];
Render Response Data
class First extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [
{id: "12497wewrf5144", name: "ABC", isVisible: "false"},
{id: "12497wewrf5255", name: "CBD", isVisible: "true"}
];,
};
}
render() {
return (
<ul>
{this.state.data.map(d => <li key={d.name}>{d.name}</li>)}
</ul>
);
}
}

React this.context returns empty object {} in React Native 0.61

I've read some documentations and answers related to this but have not found a specific answer for my case. I run my code both on React Native 0.61 (React version 16.9.0) and Snack playground.
The problem is that console.log(this.context) always returns empty object like this {}.
The code is:
import React from 'react';
import { Text } from 'react-native';
const AppContext = React.createContext({})
class App extends React.Component {
state = {
products: [
{ id: 'p1', title: 'Gaming Mouse', price: 29.99 },
{ id: 'p2', title: 'Harry Potter 3', price: 9.99 },
],
cart: []
};
render() {
return (
<AppContext.Provider
value={{
products: this.state.products
}}
>
</AppContext.Provider>
);
}
}
export default class testScreen extends React.Component {
static contextType = AppContext
render() {
console.log(this.context)
return (
<>
<Text>{'Sometext'}</Text>
</>
);
}
}
Maybe
<AppContext.Provider
value={{
products: this.state.products
}}
>
<testScreen/>
</AppContext.Provider>
I solved the issue. Solution is:
import React from 'react';
import { Text } from 'react-native';
const AppContext = React.createContext({})
class App extends React.Component {
state = {
products: [
{ id: 'p1', title: 'Gaming Mouse', price: 29.99 },
{ id: 'p2', title: 'Harry Potter 3', price: 9.99 },
],
cart: []
};
render() {
return (
<AppContext.Provider
value={{
products: this.state
}}
>
{this.props.children}
</AppContext.Provider>
);
}
}
class TestScreen extends React.Component {
static contextType = AppContext
render() {
console.log(this.context)
return (
<>
<Text>{'Sometext'}</Text>
</>
);
}
}
export default function AppComponent() {
return <App><TestScreen/></App>
}

Is it possible to make a state array from this JSON object?

A newbie in React here. I'm using axios to retrieve this object requested to my Django server rest framework Api:
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"url": "http://localhost:8000/blog/api/categories/1/",
"title": "Django",
"slug": "django"
},
{
"id": 2,
"url": "http://localhost:8000/blog/api/categories/2/",
"title": "Git",
"slug": "git"
},
{
"id": 3,
"url": "http://localhost:8000/blog/api/categories/3/",
"title": "Introduction to docker",
"slug": "introduction-to-docker"
}
]
}
So far I've been able to store those variables in separate arrays. This is the implementation of my FetchDemo.js:
import React, {Component} from 'react';
import axios from 'axios';
{/* https://daveceddia.com/ajax-requests-in-react/ */}
class FetchDemo extends Component {
state = {
urls: []
}
state = {
titles: []
}
state = {
slugs: []
}
componentDidMount() {
axios.get(`${this.props.url}${this.props.path}`).then(res => {
const urls = res.data.results.map(num => num.url);
const titles = res.data.results.map(num => num.title);
const slugs = res.data.results.map(num => num.slug);
this.setState( {urls} );
this.setState( {titles} );
this.setState( {slugs} );
});
}
render() {
return (
<div>
<h1>{`${this.props.url}${this.props.path}`}</h1>
<ul>
/// How to generate the JSX objects? ///
</ul>
</div>
);
}
}
export default FetchDemo;
Is it possible to build in the axios request a state array from this JSON object like the next one instead? How do I generate JSX with this new state categories?
this.setState({
categories: [
{url: "http://localhost:8000/blog/api/categories/1/", title: "Django", slug: "django"},
{url: "http://localhost:8000/blog/api/categories/2/", title: "Git", slug: "git"},
{url: "http://localhost:8000/blog/api/categories/3/", title: "Introduction to Docker", slug: "introduction-to-docker"},
]
}
)
I wish I knew more React and JavaScript. Any help is appreciated, thanks in advance.
There are a few things to note here.
state is a single object with multiple keys.
setState() is a single async transaction. When you are updating your state, you should update it in one go.
You can do things in a simpler way if I understand your question right. You don't have to store the values in multiple keys. It can be stored in a single key categories.
import React, { Component } from 'react';
import axios from 'axios';
class FetchDemo extends Component {
constructor(props) {
super(props);
this.state = {
categories = []
}
}
componentDidMount() {
axios.get(`${this.props.url}${this.props.path}`).then((res) => {
const urls = res.data.results.map((num) => num.url);
const titles = res.data.results.map((num) => num.title);
const slugs = res.data.results.map((num) => num.slug);
this.setState({
categories: res.data.results
});
});
}
render() {
const { categories } = this.state;
return (
<div>
<h1>{`${this.props.url}${this.props.path}`}</h1>
<ul>
{categories.length ?
categories.map(cat => (
<li key={cat.id}>
<div>{cat.title}</div>
</li>
))
:
(<li>categories not loaded yet</li>)}
</ul>
</div>
);
}
}
export default FetchDemo;

React - Data not found

I have a main component Resume and a child called Header:
class Resume extends Component {
constructor(props) {
super();
this.state = {
data: {}
}
}
componentDidMount() {
this.setState( this.state = data);
}
render() {
return (
<div className="Resume">
<Header data={this.state.header} />
<Skills data={this.state.skills} />
</div>
);
}
}
export default Resume;
class Header extends Component {
render() {
return (
<div className="header">
<h1>{JSON.stringify(this.props.data.title)}</h1>
</div>
);
}
}
My simple sample data so far is:
{
"header": {
"title": "Tim Smith's Resume"
},
"skills": [
{"name": "HTML", "duration": 14}
]
}
Why am I getting: TypeError: Cannot read property 'title' of undefined
No need to use JSON#stringify your title property is already a string.
In your componentDidMount is not like that we are setting state. Try to use
componentDidMount()
const data = {}; // Define data or get it like you want
this.setState({
...data
});
}
In your constructor where you initialize your state. You have to do this.state = { header: {}, skills: {} } not what you done.
It looks like you're not setting the state of the <Resume/> component correctly. Try the following adjustment:
componentDidMount() {
// This will set the `data` field of your component state, to the
// value of the `data` variable.
this.setState({ data : data });
}

How to get an item from an array in JSON in ReactJS?

I am trying to get an item "icon" from "weather" form following JSON
{
"coord": {
"lon": 14.33,
"lat": 49.94
},
"weather": [{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}]
}
I can't figure out how to exctract an item which is in array through render method.
My code is:
class Weather extends React.Component {
constructor() {
super();
this.state = {
'items': []
}
}
componentDidMount() {
this.getItems();
}
getItems() {
fetch('http://api.openweathermap.org/data/2.5/weather?lat=49.9415967&lon=14.3316786&appid=ed62e370682cc9e4144620905eff37e4')
.then(results => results.json())
.then(results => this.setState ({'items': results}));
}
render() {
return (
<div>
<h1>here should be an icon..</h1>
{this.state.items.weather.map(function(weather, index) {
return <h3 key={index}>{weather.icon}</h3>
})}
</div>
);
}
}
I actually used this question here: Get access to array in JSON by ReactJS ...which got me this far, but still can't make it working...
Your weather array is not set until your fetch request is complete, so this.state.items.weather.map in your render method will result in an error.
You could give weather an empty array as default value.
class Weather extends React.Component {
constructor() {
super();
this.state = {
items: {
weather: []
}
};
}
componentDidMount() {
this.getItems();
}
getItems() {
fetch(
"http://api.openweathermap.org/data/2.5/weather?lat=49.9415967&lon=14.3316786&appid=ed62e370682cc9e4144620905eff37e4"
)
.then(results => results.json())
.then(results => this.setState({ items: results }));
}
render() {
return (
<div>
<h1>here should be an icon..</h1>
{this.state.items.weather.map(function(weather, index) {
return <h3 key={index}>{weather.icon}</h3>;
})}
</div>
);
}
}
copy paste this example in codesandbox.io .you were initializing the items in constructor as array(where as fetch gave you an object) and for the initial render, items.weather was undefined and in render method you were trying to access map of undefined which was causing the error. (I have changed the url to https to run it in codesandbox)
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor() {
super();
this.state = {
items: {}
};
}
componentDidMount() {
this.getItems();
}
getItems() {
fetch(
"https://api.openweathermap.org/data/2.5/weather?lat=49.9415967&lon=14.3316786&appid=ed62e370682cc9e4144620905eff37e4"
)
.then(results => results.json())
.then(results => this.setState({ items: results }));
}
render() {
return (
<div>
<h1>here should be an icon..</h1>
{this.state.items.weather &&
this.state.items.weather.map(function(weather, index) {
return <h3 key={index}>{weather.icon}</h3>;
})}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Resources