I've defined an empty array in the react component constructor which I wish to assign with json response data from an API call
class Grid extends Component {
constructor(props) {
super(props);
this.state = {
blogs : []
};
}
I call the componentDidMount method to load data on this component where I'm using setState to assign values
componentDidMount(){
Axios.get("/api/blogs").then(response => {
const blogData = response.data;
this.setState({blogs: blogData.data});
});
}
The JSON response data is as follows (Laravel collection resource with meta and links)
{
"data": [
{
"title": "Experiments in DataOps",
"status": true,
"publish_date": "2020-01-29",
"slug": "experiments-in-dataops"
},
{
"title": "What is it about certifications anyway?",
"status": true,
"publish_date": "2020-01-29",
"slug": "what-is-it-about-certifications-anyway"
}
],
"links": {
"self": "link-value",
"first": "http://adminpanel.test/api/blogs?page=1",
"last": "http://adminpanel.test/api/blogs?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://adminpanel.test/api/blogs",
"per_page": 15,
"to": 2,
"total": 2
}
}
the blogs array however remains undefined when I'm calling it later in populating the grid data
<BootstrapTable data={this.blogs} version="4" striped hover pagination search options={this.options}>
I get an empty table, calling console.log on blogs and this.blogs reveals it's undefined.
I'm using reactstrap and react-bootstrap-table for this grid component.
You are not accessing the state correctly to access the blogs use this.state.blogs:
<BootstrapTable data={this.state.blogs} version="4" striped hover pagination search options={this.options}>
Related
Been trying all morning and for the life of me I can't get individual array data to be displayed from my API. I am trying to display one body of text from an array at a time, and can only get it to output all at once. Had it working when the data was in JSON format but now its in an array I'm struggling to make it work.
My code:
componentDidMount() {
axios
.get(
"API_DATA"
)
.then((res) => {
let data = res.data
this.setState({ data, loading: false });
console.log(data)
});
}
render() {
if (this.state.loading) {
return <Loader />
}
// return table if loading is false
// handling error goes with the same logic
// table will only render if loading is false
else
return (
this.state.data.data).map((item) => (
<>
<p key={item.id}>{item.title}</p>
</>
))
}
}
I previously used added [0] or [1] etc to determine which element I wanted to display and this worked very nicely however if I try this.state.data.data[0]).map((item) => ( It states it is not a function.
Expected output of API:
{
"data": [
{
"id": 9,
"status": "published",
"body": "TEST1",
"availability": "internal",
"title": "Test1",
"posted_by": "Tester"
},
{
"id": 10,
"status": "published",
"body": "TEST",
"availability": "internal",
"title": "TEST2",
"posted_by": "Tester"
},
I am attempting to create a simple portfolio website and am having a hard time with the portfolio item details component. I have created a list of the portfolio items as a JSON data list that will fetch assets within the app. I decided to hard-code this rather than host the data because it won't be changing too often and the artist will be updating their portfolio once or twice a year.
Here is the simple list of data in JSON:
[
{
"id": "1",
"img_code": "florida.jpg",
"creation_medium": "Adobe Illustrator",
"meta": ["graphic design", "logo", "Adobe Illustrator", "Florida Graphics & Marketing"]
},
{
"id": "2",
"img_code": "musicapp.png",
"creation_medium": "Adobe XD",
"meta": ["app design", "music app", "Adobe XD", "Florida Graphics & Marketing"]
},
{
"id": "3",
"img_code": "dreamroom.jpg",
"creation_medium": "Sketch for iPad Pro",
"meta": ["hand sketch", "digital art", "Apple Sketch", "dream office"]
},
...
]
And I am attempting to filter that list in a component to display the appropriate item on a details page. Here is the code:
import React, { Component } from 'react'
import Data from '../data/portfolio.json';
export class PortfolioDetails extends Component {
constructor(props) {
super(props);
this.state = {
itemId: this.props.location.state ? this.props.location.state.id : window.location.pathname.split('/')[2],
portfolioItem: {}
}
}
componentDidMount() {
this.fetchPortfolioItems();
}
fetchPortfolioItems() {
const data = Data.filter(item => item.id = 1);
this.setState({portfolioItem: {data} });
}
render() {
....
}
}
export default PortfolioDetails
However, instead of returning the one item with the id of 1, it changes every item's id to one. Here is what I am getting when I console log the results ...
0: {id: 1, img_code: "florida.jpg", creation_medium: "Adobe Illustrator", meta: Array(4)}
1: {id: 1, img_code: "musicapp.png", creation_medium: "Adobe XD", meta: Array(4)}
2: {id: 1, img_code: "dreamroom.jpg", creation_medium: "Sketch for iPad Pro", meta: Array(4)}
What am I missing? I thought this would be a simple use of the filter() method.
Your code explicitly tells Javascript to assign the value of 1 to every id, and of course, 1 is truthy so it returns true to the filter function.
Change
const data = Data.filter(item => item.id = 1);
to
const data = Data.filter(item => item.id == 1);
I fetch an api on componentDIdMount() then store the json to a state then I pass that state as a prop, I have no problem showing the data except on arrays.
<Component details={this.state.details} />
json:
{
"adult": false,
"backdrop_path": "/qonBhlm0UjuKX2sH7e73pnG0454.jpg",
"belongs_to_collection": null,
"budget": 90000000,
"genres": [
{
"id": 28,
"name": "Action"
},
{
"id": 878,
"name": "Science Fiction"
},
{
"id": 35,
"name": "Comedy"
},
{
"id": 10751,
"name": "Family"
}
]
}
then I try to map the genres:
<div className={style.genre}>
{details.genres.map(g => (
<span key={g.id}>{g.name}</span>
))}
</div>
But then I get Cannot read property 'map' of undefined, I don't know why this is happening because I'm able to do details.budget
It's trying to read data before you get the result from api.
so write the map function as
{details&&details.genres&&details.genres.map(g => (
<span key={g.id}>{g.name}</span>
))}
In react Initially when component is mounted, render() function is called and then componenentDidMount() is called in which you fetch data. So Initially details is empty. So you need to write the condition.
I am using react to render data from properties in a json that is nested. I don't have a problem rendering the properties that are not nested such as 'name', and 'id', but when it comes to grabbing a nested prop such as place:location{...} etc, it says "TypeError: Cannot read property 'location' of undefined"
My json format looks as follows:
data = [ {
"end_time": "2015-03-28T21:00:00-0700",
"name": "Brkn Intl. Bay Area Season 2!",
"place": {
"name": "MVMNT Studio",
"location": {
"city": "Berkeley",
"country": "United States",
"latitude": 37.85381,
"longitude": -122.27875,
"state": "CA",
"street": "2973 Sacramento St",
"zip": "94702"
},
"id": "459771574082879"
},
"start_time": "2015-03-28T15:00:00-0700" }, ...]
This is my react code:
class ResultBox extends Component {
constructor(props){
super(props);
this.state = {
posts: []
};
}
componentDidMount() {
axios.get('http://localhost:3001/api/events')
.then(res => {
let posts = res.data.map(obj => obj);
this.setState({posts});
console.log(posts);
});
}
render() {
return (
this.state.posts.map(function(events){
return <div className='result_box'>
<p>{events.name}</p>
<p>{events.place.location.city}</p> <----- This give me error!!!
</div>
})
);
}
}
Any help would be appreciated!!!!
It looks like not all events have property place defined.
You can either warn about it on every component or just ignore and prevent undefined values to be rendered:
this.state.posts.map(events =>
<div key={events.id} className='result_box'>
<p>{events.name}</p>
{events.place && <p>{events.place.location.city}</p>}
</div>
)
Lodash's get method also can help you with this:
<p>{get(events, 'place.location.city', '')}</p>
Something weird is going on:
This is my initial state (a .js file)
import moment from 'moment';
let date = moment();
var previousDate = moment("2015-12-25");
export const projects = [
{
"id": 0,
"metadata": {
"fields":
[{
"id": 1,
"order": 1,
"name": "Name",
"value": "Collection 1"
},
{
"id": 2,
"order": 2,
"name": "Created On",
"value": date
},
{
"id": 3,
"order": 3,
"name": "Last Modified On",
"value": previousDate
},
{
"id": 4,
"order": 4,
"name": "Status",
"value": "Filed"
}],
"tags":
[{
"id": 1,
"order": 1,
"value": "tag1"
},
{
"id": 2,
"order": 2,
"value": "tag2"
},
{
"id": 3,
"order": 3,
"value": "tag3"
},
{
"id": 4,
"order": 4,
"value": "tag4"
}]
}
}
This is ProjectsList.js:
import React from 'react';
import Project from './Project';
import { projects } from 'initialState';
export default (props) => {
return(
<div className="projectsList">
{projects.map(project => (
<article key={project.id}><Project fields={project.metadata.fields} /></article>
))}
</div>
)
}
And this one's Project.js:
import React from 'react';
export default (props) => {
return(
<ul className="fields">
{props.fields.map(field => <li key={field.id}>{field.name}</li>) }
</ul>
)
}
I am trying to render a bunch of projects in a list, and every project contains a bunch of metadata key-value pairs that it shows.
So basically, the wiring does not matter, it all works fine.
Except for this:
If you look up at the initial state file (first one up there), there is an array of multiple objects in fields. Each object shows 4 key-value pairs
id
order
name
value
Now, in Project.js, the line where I go
{props.fields.map(field => <li key={field.id}>{field.name}</li>) }
looks like I can switch the {field.name} for {field.id}, to show the id in text. Or I can go {field.order}, to display the order.
But weirdly enough, if I want to show the actual value of the field, like so {field.value}, it throws.
invariant.js?4599:38
Uncaught Invariant Violation: Objects are not valid as a React child (found: Mon Jun 20 2016 21:40:33 GMT-0400). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of `StatelessComponent`.
I even went as far (sigh) as changing the string value in every fields to val, juste to make sure value wasn't some kind of a reserved word.
Still threw.
Anybody can help me understand what I have done wrong, here?
Thanks Guys.
You are assigning to variable values to the value property in your state file, which are most likely not strings, but objects:
export const projects = [{
"id": 0,
"metadata": {
"fields":
[
...
{
"id": 2,
"order": 2,
"name": "Created On",
"value": date // one
},
{
"id": 3,
"order": 3,
"name": "Last Modified On",
"value": previousDate // and another one
},
...
]
...
}
}
If typeof children returns "object" (and children is neither an array, nor a ReactElement), it throws:
https://github.com/facebook/react/blob/dc6fc8cc0726458a14f0544a30514af208d0098b/src/shared/utils/traverseAllChildren.js#L169
Here's a simplest example to demonstrate this:
const IllegalComponent = () => <span>{{}}</span>
You are supposed to supply a string (or number) so that React could inline that as the children in <li>. Children should be something that's renderable and implements ReactNode.
If the children is an object, React would not know how to render it. You should explicitly convert the value to String.
Try this to see if it works:
{props.fields.map(field => <li key={field.id}>{field.value.toString()}</li>) }