How to destructure my api data in reactjs? - javascript

I am trying to destructure my array of objects with .map ? I have tried a few things but keep getting stuck. I am able to access single data by using the index but struggling with how to do it for them all.
I know it's something like this
const {name} = product;
and
const {attributes:name} = product;
but they don't work, they print "undefined".
Also tried this -
console.log(product.map(({name}) => (console.log(name))))
This is the data
console.log(product);
{
"attributes": {
"image": {
"data": []
},
"name": "test",
"description": "test product",
"price": 20,
"quantity": 0
}
}
This is what I want to achieve
<div className='grid grid-cols-4'>
{product.map(({attributes: name})=> (
<p>{name}</p>
))}
</div>

It's possible to destructer nested object.
Try something like this:
product.map(({attributes:{name}})=> ...

since it's Object this will work
const { name } = product.attributes;
or
<p>{product.attributes.name}</p>

Related

Search an element in an array component of a json file using JS

I am running this code snipped in React to search if there is a match with the user's input. The json file goes as follows:
{
"first":{
"name": "Michael Jordan",
"id": "mj"
"image": ".../icon.png",
"tags": [
"Sportsman",
"Tall",
"Famous",
"something",
"etc"
]
},
"second":{
"name": "Paul White",
"id": "pw"
"image": ".../icon.png",
"tags": [
"Engineer",
"Small",
"Famous",
"Another characteristic",
"likes apples"
"something",
"etc2"
]
}
}
and here is the search function I made to search through all the names and tags if there is a matching "person", and afterwards display all the "people" that share the same tags or names
const [q, setQ] = useState("");
function main_char_search(searchProp) {
const tagssearch = searchProp[0].tags && Object.keys(searchProp[0].tags);
return searchProp.filter(
(new_items) => new_items.name.toLowerCase().indexOf(q) > -1 ||
tagssearch.some((tagsearch)=>new_items[tagsearch].toString().toLowerCase().indexOf(q)) > -1
);
}
the trick is that the array that contains the tags varies in size sometimes.
The input is supposed to look like the JSON file. After all it is the result after fetching the JSON file using "fetch".
const [loadChar, setLoadChar] = useState([]);
fetch('./data/fakeData.json')
.then((res) => return res.json())
.then((data) => {
//more code
setLoadChar(all_the_characters_from_json_file);
})
and I call the function with:
<APageForCharacters inputInfo={main_char_search(loadChar)} />
Here is the errors that this code generates:
TypeError cannot read properties of undefined (reading 'tags')
Uncaught (in ... promise)
Note: the code runs perfectly if I try to search through the names and other individual components.
Note 2: the tagssearch variable is storing the values of tags as their index number, so the code is wrong from there, but I am still struggling to find the best solution with best time complexity.
Hopefully I am not missing any required information.

Why can I access nested objects before setting my state but not after?

I'm creating a Pokedex app using React as a practice exercise as I've just been learning it, and I'm hitting a bit of a weird snag. So the basic set up so far is I have a PokemonList component that is basically the parent component for a bunch of individual PokemonPreview components. It's in creating these PokemonPreview components and grabbing information from the pokeapi that I'm having some issues. Here's my example code from my PokemonPreview component (just the relevant bits):
const [pokemonInfo, setPokemonInfo] = useState({})
const name = props.pokemon.name.charAt(0).toUpperCase() + props.pokemon.name.slice(1)
const url = props.pokemon.url
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
console.log(data.types[0].type.name)
setPokemonInfo(data)
})
}, [])
return (
<div style={{backgroundColor: '#F06430'}} className="pokemon-preview">
<h3>{name}</h3>
<h5>#{pokemonInfo.id}</h5>
<h5>{pokemonInfo.types[0].type.name}</h5>
</div>
)
The name and url are both passed as props from the PokemonList component, and the url is then used to pull the full details for the pokemon from the pokeapi (ex: https://pokeapi.co/api/v2/pokemon/6). Basically, I'm doing the fetch request to get the data for the pokemon, and saving that whole object as my state, so I can pull whatever info from that object in state as I need it. The weird thing that I'm seeing is that I can't pull some info from my state object. Here is an example of the JSON that is stored in my state object:
{
"abilities": [
{
"ability": {
"name": "blaze",
"url": "https://pokeapi.co/api/v2/ability/66/"
},
"is_hidden": false,
"slot": 1
},
{
"ability": {
"name": "solar-power",
"url": "https://pokeapi.co/api/v2/ability/94/"
},
"is_hidden": true,
"slot": 3
}
],
"base_experience": 240,
"types": [
{
"slot": 1,
"type": {
"name": "fire",
"url": "https://pokeapi.co/api/v2/type/10/"
}
},
{
"slot": 2,
"type": {
"name": "flying",
"url": "https://pokeapi.co/api/v2/type/3/"
}
}
],
"weight": 905
}
What I'm trying to access are the entries in the types array. As you can see in the console log in my example code, I'm able to grab the first entry in the types array from the request data, but if I try to get that same info from my state using a console log or in the component's return, I get an error: TypeError: Cannot read property '0' of undefined. The pokemonInfo.id part in the return works but not the more nested types part. I really can't figure out why I'm able to get this info before setting it to my state, but not after. Does anyone know why this is happening? Should I just create separate state variables for each piece of the pokemon's information, instead of storing it in one big object to pull out later?
Thanks!
Ok so the reason for the error is you're trying to render the info before it's loaded, since the pokemon info is fetched from an API. You have to accommodate for that. Here's a basic technique:
// Set it to null initially, since it's not defined at all
const [pokemonInfo, setPokemonInfo] = useState(null);
...
// Check if the pokemon info is null before trying to access nested data
return (
<div style={{backgroundColor: '#F06430'}} className="pokemon-preview">
<h3>{name}</h3>
{
pokemonInfo === null ?
<h5>Loading pokemon data...</h5> :
<>
<h5>#{pokemonInfo.id}</h5>
<h5>{pokemonInfo.types[0].type.name}</h5>
</>
}
</div>
)
And of course make sure the object paths are all correct

React axios get data from JSON by object unique name

I have a structure like this:
{
"RESTAPI": {
"uniqueId": {
"id": "1",
"data_2": "data_2",
"data_3": true,
"mg_gateway": "Another Object"
},
"uniqueId2": {
"id": "1",
"data_2": "data_2",
"data_3": true,
"mg_gateway": "Another Object"
}
}
}
uniqueId can be with letters and numbers. I try to get it:
componentDidMount() {
axios.get('https:LINKNAME/RESTAPI.json')
.then(res => {
const fetched = res.data;
this.setState({ data: fetched });
})
}
And show in JSX:
{Object.keys(this.state.data).map((obj, i) => {
return <p key={i}>{obj}</p>
})}
In browser I can see only strings (typeof string): uniqueId and uniqueId2
But in console log I get all Objects.
console.log
But I cant show data inside each nested Object in map. So I try to use obj.data_2 and got undefined.
I thought that I can create new obj.map inside, but obj always string so it's impossible. Please, help me
You could use Object.values instead of Object.keys, then obj will be:
{
"id": "1",
"data_2": "data_2",
"data_3": true,
"mg_gateway": "Another Object"
}
or you can do this.state.data[key] as in previous replies
{Object.keys(this.state.data).map((key, i) => {
return <p key={i}>{this.state.data[key]}</p>
})}
Object.keys gives you only keys of object that is why you are only seeing the keys(uniqueId,uniqueId2)
So if you want whole data along with uniqueId do
this.state.data.map(...your code);
But I suspect you might get something like [object] so use
JSON.stringify in map function.
Or you can simply replace
<p key={i}> {this.state.data[obj]}</p>

Getting values of json array in Mocha JS

I have following issue, this json is returned by api:
"products": {
"10432471": {
"id": 10432471
},
"10432481": {
"id": 10432481
}
}
and I need to get names of all variables under products array, how to get them?
That values are constantly changing everyday, so I can not refer to their names
Trying console.log(res.body.menu.categories[i].products.values()); but its not worked.
Any sugesstion how can I get 10432471 and 10432481 from products? Without referring to variable names.
You are able to get that via Object.keys(res.body.menu.categories[i].products)
To get the object properties, the shortest is using Object.keys()
var obj = {"products": {
"10432471": {
"id": 10432471
},
"10432481": {
"id": 10432481
}
}}
var properties = Object.keys(obj.products)
console.log(properties)

Get number of current element in parent array object

I have the following JSON object and when in building the Message.jsx I would like to include as id the number of the current message element in the section array. How could I do that?
{ "sections": [
{
"message": {
"from": "someone",
"body": "ibsum"
}
},
{
"message": {
"from": "someone else",
"body": "lorem"
}
}, ... ] }
Can I actually do this without explicitly setting an id property for each object in section array?
Use the second property of map which is the element index within the array. You can set the key in the same way. Remember, indexes start from 0.
So something like this:
<Section>
{this.props.messages.map((message, i) => {
return <Message key={i} id={i} info={message} />
})}
</Section>

Categories

Resources