Render object in a select dropdown - reactjs

I'm a complete beginner to react.js and I really need some help, I'm trying to fetch some data from a mysql-database into a select-dropdown in react.js, but the data will be in an [object, Object] and does not load into the select.
My select-dropdown is not empty though, the "data" is just not visible in text. I.e, I got three items inside my food-object, and in my select-dropdown I get three BLANK items to choose between, and once I click on an "item" I get the error message saying "TypeError: Cannot read property 'map' of undefined".
I've tried the solution from (React selecting option with object as attribut value) but it does not work for (but it's the same problem though)
I've also tried to use JSON.stringify without any success. Advice is much appreciated!
class Test extends Component {
constructor(props) {
super(props);
this.state = {
food: []
};
}
componentDidMount() {
fetch('/test')
.then(response => response.json())
.then(food=> (
this.setState({food}))
);
}
render() {
console.log(this.state);
return <div className="container">
<div className="selection">
<Select options={this.state.food} className="dropdown">
{this.state.food.map((food, index) => (
<option key={index} value={index}>
{food.foodName}
</option>
))}
</Select>
<div>
<p> Listing data from mysql like this works {
this.state.food.map(food => (
<li key={food.foodName}>{food.foodName}</li>))}
</p>
</div>
</div>
</div>
}
}
export default Test;
==========================
What I can see in the console (response from the server)

Your JSON response from the server is:
{ food: [...] }
However, when you do:
.then(food => (
this.setState({ food }))
);
Your setting your state to be:
{
food: {
food: [...],
},
},
You need to access the food key in the response and set that as the value in state:
.then(response => {
this.setState({ food: response.food });
});

Related

Uncaught TypeError: Cannot read properties of undefined (reading 'map') Why this occurred after doing all the possible ways to solve

I'm using API key to iterate the data, I am getting this error again and again. I did all possible ways to solve it. I made array named articles to store all the data in it and then iterated it. It was run perfectly when I manually fetch data in it by an array but when I used API it started giving me this error.
import Newsitem from './Newsitem'
export class News extends Component {
articles = [];
constructor() {
super();
this.state = {
articles: this.articles,
loading: false
}
}
async componentDidMount() {
let url = `https://newsapi.org/v2/top-headlines?
country=in&category=business&apiKey=549bc58bb2fd419088ac863611e7339e`;
let data = await fetch(url);
let parsedData = await data.json()
console.log(parsedData);
this.setState({
articles: parsedData.articles
})
}
render() {
return (
<>
<div className='container my-3'>
<h1>News of the day - in Nutshell</h1>
<div className="row my-4">
{this.setState.articles.map((element) => {
return <div className="col-md-4 my-3" key={element.url}>
<Newsitem title={element.title ? element.title.slice(0, 45) : ""}
discription={element.description ? element.description.slice(0, 88) : ""} imgUrl=
{element.urlToImage} newsUrl={element.url} />
</div>;
})}
</div>
</div>
</>
)
}
}
export default News```
I tried all possible ways to fix this but didn't work anything of them.
Why it
Following the [React Component Article][1] "setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. This is the primary method you use to update the user interface in response to event handlers and server responses."
Therefore, I believe you mean to do this.state.articles instead of this.setState.articles.

How to store Key-Value pairs in a list or library in React JS

I want to store unique key and value in my class component state(selectedFeatures) as a list of key-value pairs, by taking the arguments which are passed from the body. ex: {“user1”:"opt1", “user2”:"opt3"}. The key must be unique, which means if the same key received from the body value should be updated to the relevant key which is stored previously
I did it in this way and it gives an error as “this.state.selectedFeatures is not iterable”. Therefore how to resolve this.
import React, { Component} from 'react';
import {features} from '../../services';
class UserData extends Component {
constructor(props) {
super(props)
this.state = {
featureTypes:[],
selectedFeatures:{}
}
}
getSelectedFeatures =(event,keyValue)=>{
const features = {};
features[keyValue] = event.target.value
this.setState({selectedFeatures: features})
}
componentDidMount(){
//http request from service component
features().then(response => {
this.setState({featureTypes:response})
})
.catch(error => {
console.log(error)
})
}
render() {
const {featureTypes} = this.state
return (
<div>
{featureTypes.map((feature, i) => (
<div key={i}>
<label>
<h4>
{feature.feature}
</h4>
</label>
<select
defaultValue="select-feature"
onChange={(event) => this.getSelectedFeatures(event, feature.feature)}>
{feature.types.map((type, i) => (
<option key={i} value={type}>
{type}
</option>
))}
</select>
</div>
))}
</div>
)
}
}
export default UserData
Without creating an array just simply adding to an object can be achieved via this method
addTo = (event, val) => {
this.setState((prev) => ({
selectedFeatures: {
...prev.selectedFeatures,
[event.target.value]: val
}
}));
};
NOTE I changed the name from getSelectedFeatures to addTo from simplicity + because get would mean it returns something. In this case, you send and add it.
the prev is a previews state that was before the state change.
Also I went a step further and created a demo project https://codesandbox.io/s/flamboyant-lake-4rvfz?file=/src/App.js
Inside of it there are multiple different containers that you may click and it will save what has been click as a event.target and a value they themself send to the method. If the container is clicked again OR a different but same type container is clicked, the value is overriten rather then added as a new parameter. Its constructed using class, as in your code. This is a simple quick demo that, after analizing, you may adapt to it as you wish with any code you want.

Can't fetch data object entirely in react, most likely due to of fetch call delay

I'm trying to get Wordpress Rest API data about author.
So I'm using ComponentDidMount() with state:
constructor(props) {
super(props);
this.state = {
data: {},
};
}
componentDidMount() {
apiFetch( { path: '/wp/v2/users/1' } )
.then(data => this.setState({ data }));
}
in my render:
const { data } = this.state;
my data will be similar to this:
{
id: "2",
name: "Alex",
image_url: {
24: "http//...",
48: "http//...",
96: "http//..."
}
}
So in my return if I do this:
<div className={className}>
{data.name}
</div>
it is working and I will get "Alexander", but if add image url:
<div className={className}>
{data.name}
<img src={data.image_url['24']} />
</div>
I will get an error Cannot read property '24' of undefined.
As I understand there is some delay for fetching and that's why I get an error.
How can I add expectation of handling?
Sorry but in React I'm a beginner.
P.S. This is actually Gutenberg editor which is actually react, but has some core like apiFetch function, it is similar to fetch.
As you said the reactive variable won't come until the response is resolved you just have to check if it exists like that
<div className={className}>
{data.name}
{ data.image_url ? (<img src={data.image_url['24']} />) : (<></>) }
</div>

Cannot read property of data null in ReactJs when fetching from JSON

I am new to react andtrying to fetch JSON data in React JS but getting this error:
TypeError: Cannot read property 'data' of null
My code is :
import React from 'react';
export default class FetchJson extends React.Component {
componentDidMount()
{
fetch('https://api.myjson.com/bins/9i63i')
.then((response) => response.json())
.then((findresponse) =>{
this.setState({ data: findresponse })
//console.log(this.state.data);
//console.log(findresponse.DesignName);
})
}
render() {
return(
<ul>
{this.state.data.map((x,i) => <li key={i}>{x.DesignName}</li>)}
</ul>
);
}
}
You can see the json data here: http://myjson.com/9i63i
I want to retrieve value for key DesignName which is part1 which is not happening.
See the commented lines: both gives me the value. But when i try to access it inside return method inside render. I get error : TypeError: Cannot read property 'data' of null in this line:
{this.state.data.map((x,i) => <li key={i}>{x.DesignName}</li>)}
How to solve this?
DesignName is not an array in the response.
You can define your state like this:
state = {
data: null
}
And display the DesignName using inline if with logical && operator to solve null problem.
render() {
return (
<div>
DesignName: { this.state.data && this.state.data.DesignName}
</div>
);
}
Codesandbox
You can use an isLoading flag while waiting for your api call to finish.
state = {
data: null,
isLoading:true
}
render() {
if(this.state.isLoading) {
return(<div>loading</div>);
}
return(
<ul>
{this.state.data.map((x,i) => <li key={i}>{x.DesignName}</li>)}
</ul>
);
when your api call has finished, you can update the state like this:
this.setState({ data: findresponse, isLoading:false })

Issue with Creating a Search Bar with React

I'm trying to create a search bar that will load a list of user's names from an api when input is added to the search bar and im getting an error. im not quite sure what to make the parameters of the .filter method. or if im even using the correct method. I thought about using lodash _.filter but not sure how or where to implement that. im new to react so keep that in mind! id be very thankful for any suggestions
import React, { Component } from "react";
import ReactDOM from "react-dom";
import './App.css'
class App extends Component {
constructor() {
super();
this.state = {
people: [],
search: ''
};
}
componentDidMount() {
fetch("https://randomuser.me/api/?page=3&results=10&seed=abc")
.then(results => results.json())
.then(data => this.setState({ people: data.results }));
}
updateSearch(event) {
this.setState({ search: event.target.value })
}
render() {
let filteredPeople = this.state.people.filter(
(people) => {
return people.data.results.indexOf(e.target.value) !== -1;
//or maybe use .includes
}
);
return (
<div className="card">
<div className="firstlast">
{filteredPeople.map(people => (
<div id="names">{people.name.first} {people.name.last}</div>
))}
</div>
<input type="text" value={this.state.search} onChange={this.updateSearch.bind(this)} />
</div>
);
}
}
export default App;
error message:
Error in /~/App.js (43:32)
Cannot read property 'results' of undefined
When you type in input, you need to use that value to filter your data,
{ this.state.search !=="" ? this.state.people.filter( people => people.name.first.includes(this.state.search)).map( (people,index) => (
<p key={index}>{people.name.first} {people.name.last}</p>
))
:
this.state.people.map((people,index) => (
<p key={index}>{people.name.first} {people.name.last}</p>
))
}
Demo
Note: I have used key={index} because I didn't find anything unique in your response, but always try to avoid using index as key.
You need to access people.results instead of people.data.results
Cause this.setState({ people: data.results }) adds data.results to people directly.

Resources