Showing JSON data in ReactJS - reactjs

I cant show the JSON response to the HTML, all I am getting is his.state.selectedData.map is not a function.
This is the payload
{
"id": 1,
"name":"john",
"age" : 22
}
This is in the constructor
this.state = {
selectedData : []
}
This is the HTTP request:
axios.post("/api/data", data)
.then(res =>{
console.log(res)
this.setState({
selectedData : res.data
})
})
And this is how I am trying to show the result
<div>
<ul>
{ this.state.selectedData.map(data => {
<li>{data.name}</li>
})}
</ul>
</div>
what I am doing wrong ?

Initially selectedData is array after the ajax you changing it to object. So map function is not going work.
class Test extends React.Component {
constructor(props) {
super(props)
this.state = {
selectedData :[]
}
}
readJson(json){
let output=[]
Object.keys(json).forEach(key=>{
output.push(
<li>{json[key]}</li>
)
});
return output;
}
render() {
return (
<div>
<ul>{this.readJson({ "id": 1,"name":"john","age" : 22 })}</ul>
</div>
)
}
}

The response from api is json object and your are trying to use map in json object will not work. Change selectedData to json object like below in the constructor
this.state = {
selectedData : {}
}
And in the code you can directly refer the name key like below and remove the map.
this.state.selectedData.name && <li>{this.state.selectedData.name}</li>

You could try something like this if you want to keep your state object as an array.
let newData = this.state.selectedData;
axios.post("/api/data", data)
.then(res =>{
console.log(res)
newData.push(res.data)
this.setState({
selectedData : newData
})
})

constructor(props) {
super(props);
this.state = {
loadedList: [],
lists: [],
};
}
componentDidMount() {
axios.get('http://localhost:3001/../static/data/terrifdata.json')
.then(response => {
this.setState({
lists: response.data,
loadedList: response.data,
isLoading: false
})
})
}
<div>
{loadedList.map((postDetail, index) => {
return (
<h5>
{postDetail.name}
</h5>
)}
}
</div>

Related

Want to get data in array from API in React Js

I want to get data in array from the API but not able to find the exact solution and i am new to React.js
I am trying to get the data in temp array from the API but not able to figure it out how to use new state as i am already using one setState in componentDidMount method.
Code till componentDidMount method:
class Apiapp extends Component{
constructor(){
super()
this.state = {
loading:true,
characters:{}
}
}
componentDidMount(){
// This means we can use the setState method as many times are we can depending on what
type of methods are we using
// this.setState({
// loading:true
// })
fetch("https://pokeapi.co/api/v2/pokemon/5")
.then(response => response.json())
.then(data => {
let tmpArray = []
for (var i = 0; i < data.game_indices.length; i++) {
tmpArray.push(data.game_indices[i])
}
console.log(data)
this.setState({
loading:false,
characters:data
})
this.setState({
loading:false,
arrCharacters:tmpArray
})
})
}
Code of render method:
render() {
let text = this.state.loading ? <h2>Loading...</h2> : <div><h2>
{this.state.characters.name}
</h2>,<h2>{this.state.arrCharacters.name}</h2></div>
// <h2>{this.state.characters.game_indices[0].version.name}</h2>
return(<div>{text}</div>)
}
}
I am trying to get all the names that is in "game_indices".
API link: https://pokeapi.co/api/v2/pokemon/ditto
Don't overcomplicate things
import React, { Component } from 'react';
class ApiApp extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
characters: {},
};
}
async componentDidMount() {
const data = await fetch('https://pokeapi.co/api/v2/pokemon/5').then((response) => response.json());
this.setState({ characters: data.game_indices, loading: false });
}
render() {
return <div>{this.state.loading ? <h2>Loading...</h2> : this.state.characters.map((i) => i.version.name)}</div>;
}
}
I'm not too sure what data you are trying to display - its not that clear from the question
There are cleaner ways to achieve the same result. However, I'd rather explain what it is wrong with your code:
Check the comments below in your code
import { Component } from 'react'
class App extends Component {
constructor() {
super()
this.state = {
loading: true,
characters: {},
}
}
componentDidMount() {
this.setState({
loading: true,
})
fetch('https://pokeapi.co/api/v2/pokemon/5')
.then((response) => response.json())
.then((data) => {
let tmpArray = []
for (var i = 0; i < data.game_indices.length; i++) {
tmpArray.push(data.game_indices[i])
}
this.setState({
loading: false,
characters: data,
})
this.setState({
loading: false,
arrCharacters: tmpArray,
})
})
}
// Code of render method:
render() {
let text = this.state.loading ? (
<h2>Loading...</h2>
) : (
<div>
<h2>{this.state.characters.name}</h2>,
{/* 1 - When the page first loads "arrCharacters" is undefined.
Therefore you need to add a condition to make sure it is not undefined.
2- You need to loop through all elements to display the name for each of them.
For that, you can use the js array method map.
3- When you display a list, you must use a unique key as attribute.
4 - After you need to check where the data you want to display lives.
In your case, it is inside an obj version. So you access it with "." or "[]"
*/}
{this.state.arrCharacters &&
this.state.arrCharacters.map((char) => (
<h2 key={char.version.name}>{char.version.name}</h2>
))}
</div>
)
return <div>{text}</div>
}
}
export default App

Display one object from fetched data undefined

I'm new to React and I'm having a hard time trying to display the first element of an array for example. I'm getting a TypeError: Cannot read property 'title' of undefined even if it's working with a console.log. Here is the code :
constructor() {
super()
this.state = {
posts: []
}
this.componentDidMount = this.componentDidMount.bind(this)
}
async componentDidMount() {
const url = "https://jsonplaceholder.typicode.com/posts";
const response = await fetch(url);
const data = await response.json();
this.setState({
posts: data
})
console.log(data); //working
console.log(this.state.posts) //working
console.log(this.state.posts[0].title) //working
}
render() {
return (
<div className="head-title"> { this.state.posts[0].title } </div>
<div className="head-body"> { this.state.posts[0].body} </div>
)
}
What am I doing wrong ?
You can do like this. In addition to my answer :
class test extends Component{
constructor() {
super()
this.state = {
posts: [],
loading :true
}
this.componentDidMount = this.componentDidMount.bind(this)
}
async componentDidMount() {
const url = "https://jsonplaceholder.typicode.com/posts";
const response = await fetch(url);
const data = await response.json();
this.setState({
posts: data,
loading:false
})
console.log(data); //working
console.log(this.state.posts) //working
console.log(this.state.posts[0].title) //working
}
}
render() {
if(this.state.loading) return null;//Dont render component
//or add ternary condition
return (
<div className="head-title"> { this.state.posts[0].title } </div>
<div className="head-body"> { this.state.posts[0].body} </div>
)
}
}
Your component will attempt to render this.state.posts[0].title while the request still hasn't finished and thus will throw an error.
Add a check to make sure your data exists for example like so:
render() {
return (
<div className="head-title"> { (this.state.posts.length > 0) ? this.state.posts[0].title : null } </div>
<div className="head-body"> { (this.state.posts.length > 0) ? this.state.posts[0].body : null} </div>
)
}

React setState of array of objects

I have an array of 10 objects (Lets call them "Blogs") which contain title, description and image-URL properties. I need to wrap each of the properties in HTML tags and export them all so they all load on a webpage together.
With my current code, I am only getting 1 of the objects in the current state loading on the page. How do I get all the objects in the same state?
class NewBlogs extends React.Component {
constructor(props) {
this.state = {
title: [],
description: [],
image: [],
loading: true
};
}
componentDidMount() {
axios.get('/new-blogs').then(data => {
const blogs = data.data;
var component = this;
for(var i in blogs) {
component.setState({
title: blogs[i].title,
description: blogs[i].description,
image: blogs[i].image,
loading: false
});
}
})
.catch(function(error) {
console.log(error);
});
}
render() {
return (
<div>
<h2>New Blogs:</h2>
<h3>{this.state.title}</h3>
<em>{this.state.description}</em>
<img src={this.state.image}></img>
</div>
);
}
}
export default NewBlogs
I haven't run/test this but try something like this
The API call appears to return a list of objects. If so just set state once the xhr completes and set loading false once.
In the react render() is where you could iterate over your list. The easiest way to do that is with '.map()'. You then simply return react elements for each object in your list.
Also let's rename 'component' to 'list'
class NewBlogs extends React.Component {
constructor(props) {
this.state = {
list: [],
loading: true
};
}
componentDidMount() {
axios.get('/new-blogs').then(data => {
// const blogs = data.data;
// var component = this;
this.setState({list: data.data, loading: false })
// for(var i in blogs) {
// this.setState({
// title: blogs[i].title,
// description: blogs[i].description,
// image: blogs[i].image,
// loading: false
// });
// }
})
.catch(function(error) {
console.log(error);
});
}
render() {
return (
<div>
{this.state.list.map(e => (
<h2>New Blogs:</h2>
<h3>{e.title}</h3>
<em>{e.description}</em>
<img src={e.image}></img>
))}
</div>
);
}
}
export default NewBlogs

Reactjs - Assigning json response to default array

I'm using react-image-gallery for displaying gallery. I need to load images from json response. My code follows,
let imagesArray = [
{
original: 'images/products/4.jpg'
},
{
original: 'images/products/2.jpg'
},
{
original: 'images/products/3.jpg'
}
];
export default class Products extends React.Component {
loadGallery () {
var requestUrl = 'http://myurl';
var myInit = { method: 'GET',
mode: 'cors',
cache: 'default' };
fetch(requestUrl).then(response =>
response.json().then(data => ({
data: data,
status: response.status
})
).then(res => {
let imagesArray = imagesArray.map((img,i)=>{ return {original: res.data[i].path.split(':')[1]}})
}));
}
render() {
return (
<div className="products-page" onLoad={ this.loadGallery() }>
<ImageGallery
ref={i => this._imageGallery = i}
items={imagesArray}/>
</div>
);
}
}
I got an error of Uncaught (in promise) TypeError: Cannot read property 'map' of undefined
if I use let newArray = imagesArray.map((img,i)=>{ return {original: res.data[i].path.split(':')[1]}}) it will assign the value to newArray
Here how can I assign the json response to imagesArray?
If what I understand is correct you want to load a set of images and pass the data as array to ImageGallery component.
There is also something wrong/undesired with your code:
When you do this,
<div className="products-page" onLoad={this.loadGallery()}>
You will actually invoke the function loadGallery() on each render, instead you should only pass the function prototype.
<div className="products-page" onLoad={this.loadGallery}>
Below you will see another approach to implement your requirement. Here we will load the images and update Product component's state with new imagesArray from JSON response. So when the state updates, component re-renders and will pass the new data to ImageGallery component.
const dummyImagesArray = [
{
original: 'images/products/4.jpg'
},
{
original: 'images/products/2.jpg'
},
{
original: 'images/products/3.jpg'
}
];
export default class Products extends React.Component {
constructor(props) {
super(props);
this.state = {
imagesArray: dummyImagesArray
}
}
loadGallery () {
var requestUrl = 'http://myurl';
var myInit = { method: 'GET',
mode: 'cors',
cache: 'default' };
fetch(requestUrl).then(response =>
response.json().then(data => ({
data: data,
status: response.status
})
).then(res => {
const imagesArray = this.state.imagesArray.map((img,i) => { return { original: res.data[i].path.split(':')[1] }; });
this.setState({ imagesArray });
}));
}
render() {
return (
<div className="products-page" onLoad={this.loadGallery}>
<ImageGallery
ref={i => this._imageGallery = i}
items={this.state.imagesArray}
/>
</div>
);
}
}
So JSON does not actually exist in React. What you will likely need to do here is set up a class that represents the JSON data and returns it to the map. What map is basically doing is peeling back the layers of your object one by one. So something like,
class ImagesArray extends React.Component() {
render() {
return {
<image src={this.props.original}/>
}
}
}

Rendering data from an array of objects

I have integrated the search filter and retrieved the json data( array of objects ) using the post method based on the search term. The json output is given below:
[
{"taxi_code":"CT0001","class":"0"},
{"taxi_code":"CT0002","class":"0"},
{"taxi_code":"CT0003","class":"0"}
]
But the json data is not rendered to the DisplayTable component even using map method. What i did wrong?? Using console.log(<DisplayTable data={queryResult} />), i got this type of output: Object { props={...}, _store={...}, $$typeof=Symbol {}, more...}
class Results extends Component
{
constructor(props){
super(props);
this.state={searchTerm:''};
}
render(){
return(<div id="results" className="search-results">
{this.props.data}
<SearchInput className="search-input" onChange={e=>this.searchUpdated(e)} />
</div>);
}
searchUpdated (e) {
this.setState={searchTerm: e};
var queryResult;
axios.post(config.api.url + 'public/getAttributesbyname', {'searchTerm':e,'name':this.props.data})
.then(response => {
var queryResult = response.data;
render()
{
return (<DisplayTable data={queryResult}/>);
}
})
.catch(response => {
});
}
}
class DisplayTable extends Component
{
render()
{
return this.props.data.map((alldata)=> {
return <div className="station">{alldata.taxi_code}</div>;
});
}
}
You have several mistakes in your code,
You can't return values from asynchronous function(axios.post)
this.setState is method and you have to call it this.setState() but not assign value to it
I think in this case you don't need handle state from input field searchTerm, you can get value from input and use it., however you should handle state for data which you get from server.
I've refactored your example, and now it looks like this
class Results extends Component {
constructor(props) {
super(props);
this.state = { data: [] };
}
render(){
return <div id="results" className="search-results">
<DisplayTable data={ this.state.data } />
<SearchInput
className="search-input"
onChange={ e => this.searchUpdated(e) }
/>
</div>;
}
searchUpdated (e) {
axios
.post(config.api.url + 'public/getAttributesbyname', {
searchTerm: e.target.value,
name: this.props.data
})
.then(response => {
this.setState({ data: response.data });
})
.catch(response => {});
}
}
class DisplayTable extends Component {
render() {
const stations = this.props.data.map((alldata, index) => {
return <div className="station" key={ index }>{ alldata.taxi_code }</div>;
});
return <div>{ stations }</div>
}
}

Resources