Displaying json arrays in React - javascript

I'm using React to display data,and I want to display data inside hits, which is array of recipes.Below is the structure. I want to list the properties inside each recipe.
recipe": {
"uri": "http://www.edamam.com/ontologies/edamam.owl#recipe_d090689494d5bc05e53e4a808bf6db1c",
"label": "Recipe For (A Kind Of) Pisto, With Rice And Eggs",
"image": "https://edamam-product-images.s3.amazonaws.com/web-img/b7c/b7c8284b065e055f74c59f3f88718b84.jpg?X-Amz-Security-Token=IQoJb3JpZ2luX2VjEPH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLWVhc3QtMSJIMEYCIQDpnaXhSzGfXCmxvypbyEuHsQoaEVX9tsSxAHEAttR%2FuAIhAI%2Bso6mALweGSGbfFqjijfLZYKlNjx9vofkJPPR3o4P9KtUECPr%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEQABoMMTg3MDE3MTUwOTg2Igw%2FjCzJyZGmSs%2BA5uQqqQT3216RtVYOtYQ68ewLqgYN3afBsemEChcI0wO9St%2Fvk67aOwBGyJGwiaQCoLNaqIGobQXfkrtHjRPQVqNcTqtsRS4Qi%2B0tSSc%2BpodO5fpBejLyaUsEtP9REXSNjWdGSS%2BucN7yi5ObnF5O6DkWDxYVvA4vbisr%2FNkA2A7qPIyALSH7l7DQkvJDsMj%2BaKBxM3Ct3c019gbNplPbqL6XfG2iUPyUqGX0roUhOc2dcRLJWEh2urg6%2Fnla97k5hCUCV437I4vlT622Zr%2FpDpy%2FvnEwUNidqbS7B3u4oGmTNbQMGSx6h5TjmHIHqDoQzPnfsWs62GxYglzS55d%2BJhtL2tldl3y2iR%2FlDMXT1ejlz5YpU2dYpJzYKiM%2FhzHU8h8dJcTKoqmjjKMtMsp3XEfdfC7JNN5S%2BKQQdgIAjL%2B0n4aKWkPmddsP3pHi4bHGEbDrc2GUUUjHJMUityTKPb1sEieg0%2F%2FlLrhoi4Mj1%2BudlaT4Vmor9S4EIxnnRIDq5V0o1rUsLj784%2BfLBReZTCPa%2BOxT0ZpF%2FJyl9dZfakqCEXSdjWjzX07b08uTzYJIfyfwKHWrzW32wJ4aRUR7WdCcJ3n0rmjgpqKX6ozOeS8R5TP7HFeyVQcWcCyzmKDCSV40y761TasY%2BV5sqlURzjBL8%2F2iyztTydDhjopyQ1PBiewJeA06oRY4Ql3WiEySmRI4GwHOzyJOy7GY%2Fr27ZuVRolbX%2BP%2BworkCZpLrMMLAhZwGOqgBSIfkg1IG0s7EX17nVG89NMfvCCN4WXfempWOHkP2qAZtXrZOHyumjT4DUY2rDbbcqmVYBKAysjFa9NE%2BceP7%2BBNXLBBh4%2FMmaqvjZP1DYaRAj1ldEZr7E%2BNuLrADKB0Vb2pWv7mLYMcTzXzcOOLeabpSMPMsPyLNqkOr%2BperyDw6pSGebOajGpQA0QTV1m4z3HijmRicL2LLW4q5RooyF2oR5QKBu8%2Fk&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20221126T013542Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Credential=ASIASXCYXIIFP4CCVRCC%2F20221126%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=68656c34e850742a7b45117e905bbb71babec459015201e4246e65a5d6946d3b",
"source": "Mostly Eating",
"url": "http://www.mostlyeating.com/in-praise-of-pisto-and-a-perfectly-balanced-meal",
"shareAs": "http://www.edamam.com/recipe/recipe-for-a-kind-of-pisto-with-rice-and-eggs-d090689494d5bc05e53e4a808bf6db1c/tomato%2Cegg%2Cspinach",
"yield": 2.0,
"dietLabels": [
"Balanced",
"High-Fiber"
],
"healthLabels": [
"Vegetarian",
"Pescatarian",
"Dairy-Free",
"Gluten-Free",
"Wheat-Free",
"Peanut-Free",
"Tree-Nut-Free",
"Soy-Free",
"Fish-Free",
"Shellfish-Free",
"Pork-Free",
"Red-Meat-Free",
"Crustacean-Free",
"Celery-Free",
"Mustard-Free",
"Sesame-Free",
"Lupine-Free",
"Mollusk-Free",
"Alcohol-Free",
"Kosher"
],
"cautions": [ ]
}
Here is my code.
import React, { Component } from 'react';
import axios from 'axios'
import CallAPI from './CallAPI';
const api = 'http://localhost:5000' // backend address
class GetRecipe extends Component{
constructor(props){
super(props)
this.state={
list:[]
}
this.setState=this.setState.bind(this)
}
getData=()=>{
var url = `${api}/getRecipe`;
axios.get(url)
.then(response=>{
console.log(response.data)
this.setState({list:response.hits})
}).catch(err=>console.log(err))
}
render(){
return(
<div>
<h2>Get Recipe</h2>
<button onClick={this.getData}>Get</button>
<p>{this.state.list}</p>
</div>
)
}
}
export default GetRecipe;
Using the above code, there is no error, but nothing display in the page. So I tried another way:
<ul>
{this.state.list.map((value, key)=>{
return<li key={key}>{value}</li>
})}
</ul>
However, in this way I got error
getRecipe.js:37 Uncaught TypeError: Cannot read properties of undefined (reading 'map')
at GetRecipe.render (getRecipe.js:37:1)
I also try to change the getData function, then I got TypeError: Cannot read properties of undefined (reading 'setState').
getData(){
axios.get(`${api}/getRecipe`)
.then((response)=>{
this.setState({list:response.data})
})
.catch(function (error){
console.log(error)
})
}
I try this way of displaying dat before, but I don't know why it doesn't work this time. How can i make it work ?

In your first try, you have this line:
this.setState({list:response.hits})
This should (probably) be:
this.setState({list:response.data.hits})
This resolves your (first) TypeError.
Then you try to render it like this:
<p>{this.state.list}</p>
What is React supposed to do with this? It won't magically create HTML elements for your array.
Mapping over the array is the correct way to render an element per item in the array. But:
return<li key={key}>{value}</li>
value is a plain object. How is React supposed to render it? And consider using a real key, not just the array index.
Your change of getData() makes it forget this. You probably meant to bind it in the constructor instead of setState(). This resolves your second TypeError. Or change it back to an arrow function.

Related

LWC: What's wrong with the Wire Return code?

Problem is with this line in JS code inside result function-
return this.wirestoredrecords.data.LastName;
I am trying to get the Contact Fields Values using Getter and display in the HTML. PLS HELP.
**JS CODE:**
import { api, LightningElement, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import Name from '#salesforce/schema/Contact.Name';
import LastName from '#salesforce/schema/Contact.LastName';
import Phone from '#salesforce/schema/Contact.Phone';
const contactfields = [Name, LastName, Phone];
export default class WireGetRecords extends LightningElement {
#api recordId;
datavalue;
#wire(getRecord, { recordId: '$recordId', fields: contactfields })
wirestoredrecords;
get result(){
return this.wirestoredrecords.data.LastName;
}
}
**HTML CODE:**
<template>
<lightning-card>
<div>{recordId}</div>
<div>{result}</div>
<div></div>
</lightning-card>
</template>```
Your component loads to the page and the #wire is called.
The component doesn't wait for #wire to finish, it'll be done when it'll be done, asynchronous. Your component carries on.
It encounters the html rendering, calls your getter. Well, the variable is undefined/null at that point, #wire didn't return yet. The code tries to do null.data and throws because null/undefined doesn't have fields.
Boom, headshot.
Put some null checking in the getter or use the ?. operator

Why am I unable to access the data property on this object?

I am working on my first React project and in this project I'm storing images on MongoDB. (Not best practice, I know, but regardless...)
My mongoDB object has a number of properties, including one property called "coverImage" which is an object that holds two properties: type & data, which looks like this: {Type: buffer, data: Array(6450).
I'm having trouble accessing the data property. When logging to the console the value of the data property within axios, the buffer is logged to the console without issue.
Meanwhile, when attempting to access this value, which was stored in state, I receive a TypeError: "Cannot read property data of undefined"
What am I doing wrong?
Please see my code below:
import React, { Component } from "react";
import axios from "axios";
// import BookCover from "../utilities/BookCover";
class BookPage extends Component {
constructor(props) {
super(props);
this.state = {
book: ""
};
}
componentDidMount() {
axios
.get("http://localhost:3000/books/" + this.props.match.params.id)
.then(res => {
console.log("first object", res.data.coverImage); // Returns fist object, {type: Buffer, data: Array(6450)}
console.log("buffer", res.data.coverImage.data); // Returns buffer (6450) [255, 216 ...]
this.setState({
book: res.data
});
});
}
bookDetails() {
console.log("second object", this.state.book.coverImage); // Returns second object, {type: Buffer, data: Array(6450)}
// console.log(this.state.book.coverImage.data); // Returns TypeError: "Cannot read property data of undefined"
return (
<div>
<h1>{this.state.book.title}</h1>
<p>Author: TBD</p>
<p>Publish Date: {this.state.book.publishDate} </p>
<p>Need to Read: {String(this.state.book.unread)} </p>
<p>Page Count: {this.state.book.pageCount} </p>
<p>Description: {this.state.book.description} </p>
</div>
);
}
render() {
return (
<div>
<div>{this.bookDetails()}</div>
</div>
);
}
}
export default BookPage;

Browser error says "Cannot add property *, object is not extensible" - Even though property does exist in the class definition

I using React w/Sails.js backend. I think this question really only pertains to React/javascript.
I am getting the following browser console error even though the property being changed does exist in the object:
Cannot add property *, object is not extensible
Below is the class definition and the error occurs in the use of:
onExchangeSelect={selectedExchange => this.setState({selectedExchange})
in the render function below. That is, the browser complains the object is not extensible and gives that lines as the reason (and when I remove the onExchangeSelect function the error goes away).
class ExchangeContainer extends Component {
constructor(props) {
super(props);
this.state = {
exchanges:[
{
name:"binance",
url:"https://bittrex.com"
},
{
name:"bittrex",
url:"https://bittrex.com"
}
],
selectedExchange:null
};
}
render() {
return (
<div className="ExchangeContainer list-group">
<ExchangeList
exchanges={this.state.exchanges} selected={this.state.selectedExchange}
onExchangeSelect={selectedExchange => this.setState({selectedExchange}) }
/>
<ExchangeDetail exchange={this.state.selectedExchange} />
</div>
);
}
}
My question, what might be causing the error and subsequent failure for the React component to render? Why can't I change that property?
Try to spread/copy the object (otherwise, it is just using same memory location).
onExchangeSelect={selectedExchange =>
this.setState({
selectedExchange: {...selectedExchange}
})
}

How can I pass an object from container to class in Meteor and React?

I'm trying to get a value in an object of javascript but it fails somehow. I managed to get an intended data from mongoDB by findOne method. Here is my code and console log.
const title = Questions.findOne({_id: props.match.params.id});
console.log(title);
Then console says:
Object {_id: "bpMgRnZxh5L4rQjP9", text: "Do you like apple?"}
What I wanna get is only the text in the object. I have already tried these.
console.log(title.text);
console.log(title[text]);
console.log(title["text"]);
console.log(title[0].text);
But I couldn't access to it... The error message is below.
Uncaught TypeError: Cannot read property 'text' of undefined
It sounds super easy but I couldn't solve by my self. Could anyone help me out?
Additional Context
I'm using Meteor and React. I would like to pass the text inside of the object from the container to the class. I would like to render the text in render(). But it doesn't receive any data from the container... The console.log in the container works well and shows the object.
import React, { Component } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import { Questions } from '../../api/questions.js';
import PropTypes from 'prop-types';
import { Answers } from '../../api/answers.js';
import ReactDOM from 'react-dom';
import { Chart } from 'react-google-charts';
class MapClass extends React.Component{
handleAlternate(event){
event.preventDefault();
const country = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
Answers.insert({
country,
yes: false,
question_id:this.props.match._id,
createdAt: new Date(), // current time
});
ReactDOM.findDOMNode(this.refs.textInput).value = '';
}
handleSubmit(event) {
event.preventDefault();
const country = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
Answers.insert({
country,
yes: true,
question_id: this.props.match.params.id,
createdAt: new Date(), // current time
});
ReactDOM.findDOMNode(this.refs.textInput).value = '';
}
constructor(props) {
super(props);
this.state = {
options: {
title: 'Age vs. Weight comparison',
},
data: [
['Country', 'Popularity'],
['South America', 12],
['Canada', 5.5],
['France', 14],
['Russia', 5],
['Australia', 3.5],
],
};
this.state.data.push(['China', 40]);
}
render() {
return (
<div>
<h1>{this.props.title.text}</h1>
<Chart
chartType="GeoChart"
data={this.state.data}
options={this.state.options}
graph_id="ScatterChart"
width="900px"
height="400px"
legend_toggle
/>
<form className="new-task" onSubmit={this.handleSubmit.bind(this)} >
<input
type="text"
ref="textInput"
placeholder="Type to add new tasks"
/>
<button type="submit">Yes</button>
<button onClick={this.handleAlternate.bind(this)}>No</button>
</form>
</div>
);
}
}
export default MapContainer = createContainer(props => {
console.log(Questions.findOne({_id: props.match.params.id}));
return {
title: Questions.findOne({_id: props.match.params.id})
};
}, MapClass);
The problem here is that at the moment when the container is mounted, the data is not yet available. Since I do not see any subscriptions in your container I assume that you handle that elsewhere and thus there is no way of knowing when the data is ready. You have 2 options.
1) move the subscription into the container and use the subscription handle ready() function to assess if the data is ready. Show a spinner or something while it is not. Read this.
2) use lodash/get function (docs) to handle empty props. You would need to
npm install --save lodash
and then
import get from 'lodash/get';
and then in your class render method:
render() {
const text = get(this.props, 'title.text', 'you-can-even-define-a-default-value-here');
// then use `text` in your h1.
return (...);
}
Does this work for you?

Vuex how to Access state data on component mounted or created hook?

I'm trying to create a Quill.js editor instance once component is loaded using mounted() hook. However, I need to set the Quill's content using Quill.setContents() on the same mounted() hook with the data I received from vuex.store.state .
My trouble here is that the component returns empty value for the state data whenever I try to access it, irrespective of being on mounted() or created() hooks. I have tried with getters and computed properties too. Nothing seems to work.
I have included my entry.js file, concatenated all the components to make things simpler for you to help me.
Vue.component('test', {
template:
`
<div>
<ul>
<li v-for="note in this.$store.state.notes">
{{ note.title }}
</li>
</ul>
{{ localnote }}
<div id="testDiv"></div>
</div>
`,
props: ['localnote'],
data() {
return {
localScopeNote: this.localnote,
}
},
created() {
this.$store.dispatch('fetchNotes')
},
mounted() {
// Dispatch action from store
var quill = new Quill('#testDiv', {
theme: 'snow'
});
// quill.setContents(JSON.parse(this.localnote.body));
},
methods: {
setLocalCurrentNote(note) {
console.log(note.title)
return this.note = note;
}
}
});
const store = new Vuex.Store({
state: {
message: "",
notes: [],
currentNote: {}
},
mutations: {
setNotes(state,data) {
state.notes = data;
// state.currentNote = state.notes[1];
},
setCurrentNote(state,note) {
state.currentNote = note;
}
},
actions: {
fetchNotes(context) {
axios.get('http://localhost/centaur/public/api/notes?notebook_id=1')
.then( function(res) {
context.commit('setNotes', res.data);
context.commit('setCurrentNote', res.data[0]);
});
}
},
getters: {
getCurrentNote(state) {
return state.currentNote;
}
}
});
const app = new Vue({
store
}).$mount('#app');
And here is the index.html file where I'm rendering the component:
<div id="app">
<h1>Test</h1>
<test :localnote="$store.state.currentNote"></test>
</div>
Btw, I have tried the props option as last resort. However, it didn't help me in anyway. Sorry if this question is too long. Thank you for taking your time to read this. Have a nice day ;)
I copied your code and tested it ( of-course I created my own dummy notes so I could remove the get request ) and I was able to get the notes display on a page.
A couple of things that I realized from your code, you may need to add a store property as there are places in your component ( test ) where you are referencing it, yet you only define it on the 'app' component. So in this section of your code modify as shown below:
props: ['localnote'],
data() {
return {
localScopeNote: this.localnote,
store : store
}
},
The key difference is the definition of the 'store' property. Please note that, what you have done, defining a "store" property in your app component, is correct, but the very same needs to be defined in "test" component as I have shown in the above code snippet above.
Second thing is, you are using $store and I guess that gives you undefined, unless as you said, in the libraries that you included this resolves accordingly, but on my side I had to remove all references of "$store" and replace it with just "store" (without the dollar sign).
Lastly for testing purposes, I would advise you to also

Categories