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>
Related
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>
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.
In react-admin, I have an input whose source is a list of objects.
<CheckboxGroupInput source="binded_cameras" choices={choices}/>
The binded_cameras list looks like this:
"binded_cameras": [
{
"id": 1,
"name": "Cam 1",
"url": "dummyurl.com"
},
{
"id": 4,
"name": "Cam 2",
"url": "dummyurl.com"
}
]
I am trying to get only the list of id to deal with.I tried binded_cameras.id but of course it did not work.
How do I manipulate this list of objects, and generate only a list of ids?
Since React-admin uses react-final-form, you can it's use parse() and format() functions to transform the input value when saving to and loading from the record, just pass them as props to Input, in this case CheckboxGroupInput:
Mnemonic for the two functions:
parse(): input -> record
format(): record -> input
<CheckboxGroupInput
source="binded_cameras"
choices={choices}
parse={ids => ids.map(id => ({id}))}
format={bindedCameras => bindedCameras.map(b => b.id)}
/>
https://marmelab.com/react-admin/Inputs.html#transforming-input-value-tofrom-record
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>
I have an object containing multiple other objects, inside these nested objects is an array containing multiple objects, each with a uid. I'm trying to loop over the objects and find the object that contains a particular uid.
My data looks like this
const data = {
"3c5671fde44f44f9ad59d59eb810d87e": {
"heading": "Heading 1",
"items": [
{
"content": {
"uid": "4fcd5f4af7a448d48463d4e0a11297d9"
}
},
{
"content": {
"uid": "31f975440a0a431592e127b2891cd142"
}
}
]
},
"ea80e8315b554c9bb40958a6cacf4b0c": {
"heading": "Heading 2",
"items": [
{
"content": {
"uid": "d6de8db4c2a74da6915a44d3964277d6"
}
}
]
}
}
The uid I want to search for is d6de8db4c2a74da6915a44d3964277d6 when found I want to return it's parent object so I can access the heading property.
Current code looks like this but it doesn't work, it's been a long day so I'm likely missing something really simple.
const currentUid = "d6de8db4c2a74da6915a44d3964277d6";
const currentHeading = Object.keys(data).forEach(section => {
return data[section].items.filter(item => {
return item.content.uid === currentUid;
});
});
When debugging it successfully evaluates to true when it finds the correct uid, it just doesn't return anything.
Any help welcome!
forEach is meant just for looping the array, use find to find the key of your object from Object.keys(data). And inside the callback use some instead of filter to check the existance. This solution will result in either the key of the object or null. To get the object, just check that a key is returned and then use that key to get the object:
const currentHeadingKey = Object.keys(data).find(section => {
return data[section].items.some(item => {
return item.content.uid === currentUid;
});
});
const currentHeading = currentHeadingKey != null ? data[currentHeadingKey] : null;
currentHeading is now either the whole object if found, null otherwise. You can access the heading property of that object.
Note: Since the callbacks of both find and some have only one statement in them, you can use the implicit return of arrow function to shorten the code:
const currentHeadingKey = Object.keys(data).find(section =>
data[section].items.some(item => item.content.uid === currentUid)
);
Consider using the Object.values() method instead, to extract the "parent heading" for the supplied uid.
Taking this approach, you can iterate the values of data, and filter those section values that contain items matching the uid. In the answer below, this is done via:
return items.some(item => item.content.uid === currentUid)
Finally, you can map() the filtered sections to acquire the corresponding heading(s) of section with matching uid items:
function findHeading(data, uid) {
return Object.values(data).filter(section => {
// Find any item with matching uid in this section, filter this section accordingly
return section.items.some(item => item.content.uid === currentUid)
})
.map(section => {
// Map heading from any sections matching item uid
return section.heading
});
}
const data = {
"3c5671fde44f44f9ad59d59eb810d87e": {"heading": "Heading 1","items": [{"content": {"uid": "4fcd5f4af7a448d48463d4e0a11297d9"}},{"content": {"uid": "31f975440a0a431592e127b2891cd142"}}]},"ea80e8315b554c9bb40958a6cacf4b0c": {"heading": "Heading 2","items": [{"content": {"uid": "d6de8db4c2a74da6915a44d3964277d6"}}]}
}
const currentUid = "d6de8db4c2a74da6915a44d3964277d6";
console.log(findHeading(data, currentUid))