Looping over an array as a value in a JSON (javascript/react) - javascript

I have a JSON of team members:
[
{
"name": "Allie Armstrong",
"title": "Head of Finance",
"teams": ["Finance", "Europe"]
},
....]
I map over it, it's fine.
{teamMembersList.map(teamMember => {
return(
<TeamMember
teamMembers={teamMember}
/>
)
})}
But the teams part comes together.
I would like to basically get teammember.teams[0], then teammember.teams[1] etc, so they can be in their own span. Instead of having them as FinanceEurope
The number of elements in this array varies.

TRY :
{ if(teamMembersList.teams && teamMembersList.teams.length) {
teamMembersList.teams.map(teamMember => {
return( <TeamMember teamMembers={teamMember} />)
})
} else {
return('')
}
}
Also you need to check if teamMembersList.teams have some value because if it returns undefined / null OR string then it will not work and will give you error.

In the end I moved my JSON data into the js file as a const.
Then:
{teamMembersList.map(x => {
return x.teams.map(teams => (
<li key={x.id}>
{teams}
</li>
))
})}
It works fine :)

Related

react Map is not returning any jsx

I am looping over the people array and getting the first array. My screen should say "person 1". but it is blank and
nothing is being returned.
const people = [
[
{
name: 'person 1'
}
],
[
{
name: 'person 2'
}
],
]
export default function Index() {
return (
<>
{people.slice(0,1).map((person) => {
return <h1>{person.name}</h1>
})}
</>
)
}
the code works when i do this, but I need to use slice
export default function Index() {
return (
<>
{people[0].map((person) => {
return <h1>{person.name}</h1>
})}
</>
)
}
people.slice(0, 1), unlike you'd expect, returns [[{ name: "person 1" }]], not [{ name: "person 1" }] (Array#slice returns a "slice" of an array, and in your special case it's an array with a single value, but not the single value itself). You'll have to access the inner array to get what you want:
// in your JSX
people.slice(0, 1).map(([person]) => (
<h1>{person.name}</h1>
))
Notice that the argument destructures the input array (this assumes each value in people is an array with exactly one element; if not, loop over that content).
Another option would be to Array#flatMap to "un-nest" those values:
// in your JSX
people.slice(0, 1).flatMap(person => (
<h1>{person.name}</h1>
))
This will work:
return (
<>
{people.slice(0,1).map((person) => {
return <h1>{person[0].name}</h1>
})}
</>
)
Because each person is still an array, you can't access the object's properties directly without first accessing the array that wraps it.
You have to modify the data structor of people.
const people = [
{
name: 'person 1'
},
{
name: 'person 2'
}
];
In you case, person in map method is Array type. So, person.name's value will be undefined.

Loop through JSON in JSX

I have a tree like JSON structure and it can be n levels deep. Here is an example:
"plot": {
"population": "All",
"gates": [
{
"name": "population1",
"plot": {
"population": "population1",
"gates": [
{
"name": "population3",
"plot": {
"population": "population3",
}
}
]
}
},
{
"name": "population2",
"plot": {
"population": "population4",
}
}
]
};
It starts with plot. The is the top level. A plot can have many gates. These are essentially branches. Each gate has another plot, which can have multiple gates etc.
I want to output the plot.population within JSX wrapped in a div. Here is my attempt (MultiStainState is a JSON file with the above JSON):
function Plot(props) {
...
const renderPlots = (plotObject) => {
console.log("plotObject is ", plotObject);
if (plotObject) {
return (
<>
<div>{plotObject.population}</div>
</>
);
}
{
plotObject.gates.map((gate, gateIndex) => {
plotObject(gate.plot);
});
}
};
return (
<div
style={{
height: "200px",
}}
>
Render Plots:
{renderPlots(MultiStainState)}
</div>
);
}
This output Render Plots:All and none of the child plot populations.
This is presumably because of the return within renderPlots(). I feel like I need to use recursion here (as I have attempted to do). But I cant figure out how....
The main issue with your renderPlots function is that if the given plotObject is non-null, the function just returns plotObject.population and never gets to the recursive step. There are some other issues with that function, but I'm going to offer a rewrite that will address those.
I'm not sure of your exact desired output format, but I'm going to use nesting <div> elements so that the DOM hierarchy matches the JSON structure.
You'll want to return a single JSX object with the recursive step within (recursion looks a bit weird in React/JSX compared to usual programming). I've also split the renderPlots function into a separate component, but that's more of a stylistic choice (I'll leave you to find a better name for the component).
Here's a simple example:
function PlotRender({ plotObject }) {
if (!plotObject) {
return null; // just in case
}
return (
<div>
{plotObject.population}
{plotObject.gates?.map(e => (
<PlotRender key={e.name} plotObject={e.plot}/>
))}
</div>
);
}
Which will render as (for the given sample data):
<div>
All
<div>
population1
<div>
population3
</div>
</div>
<div>
population4
</div>
</div>
Note also that in the outer <Plot> component, you'll likely need to pass MultiStainState.plot as the plotObject prop to <PlotRender> rather than just MultiStainState.
Here is a simple rendering of a recursive component based on this article. It checks if it has a gates array of length > 0 and if so will recursively render the component
sandbox
const plot = {
"population": "All",
"gates": [
{
"name": "population1",
"plot": {
"population": "population1",
"gates": [
{
"name": "population3",
"plot": {
"population": "population3",
}
}
]
}
},
{
"name": "population2",
"plot": {
"population": "population4",
}
}
]
}
const RecursiveComponent = ({ population, gates }) => {
const hasGates = gates && gates.length
return (
<React.Fragment>
<div>
{population}
</div>
{hasGates && gates.map(({name,plot}) => <RecursiveComponent key={name} population={plot.population} gates={plot.gates} />)}
</React.Fragment>
);
};
const App = props => {
return (
<RecursiveComponent population={plot.population} gates={plot.gates} /> //starting point
);
};
ReactDOM.render(<App />, document.getElementById("app"));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="app"></div>

Error in displaying where there's an a array inside of the object

this is what the data shows inside the console:
I tried displaying it with these but it failed
{Object.entries(value).map(([key, value]) => {
return (
<p key={key}>
<li>
{key}
{value}
{console.log(value.id)} //this will show as undefined
</li>
</p>
);
})}
{value} will show this error :
Objects are not valid as a React child (found: object with keys {color, quantity}). If you meant to render a collection of children, use an array instead.
{value.id} or the {value.name} will show as undefined
With the map, it will say that value.map is not a function
{value.map((value, key) => (
<>
<div>{value.id}</div>
<div>{value.name}</div>
</>
))}
codesandbox: https://codesandbox.io/s/display-the-manipulated-data-dy204r
Your object has a complex structure, and in order to iterate, you need to check if one of the items is Array using Array.isArray(), if yes, then loop them and use, else use the properties directly
Below is the working code of the mock of your object and iteration. I have just logged the values, you can use them in any way you want
let myObj = {
s: [{
color: 'a',
q: '8'
}, {
color: 'b',
q: '2'
}],
name: 'Anne',
id : 18
}
Object.keys(myObj).forEach(function(key) {
if (Array.isArray(myObj[key])) {
myObj[key].forEach(function (item, index) {
console.log(item.color);
console.log(item.q);
});
}
else
console.log(myObj[key])
});
You can do something like this
{Object.entries(value).map((v, key) => {
return (
<p key={key}>
<li>
{key}
{v.name}
{console.log(v.id)} //this will show as undefined
</li>
</p>
);
})}

React use map to acces nested objects when object key is unknown

I am working on a NextJs project with a Firebase Store.
I access a collection and get an array with objects with a random key and as value the data:
const data = [
{
randomdocid67233: {
name: "ABC",
latinName: "DEF"
}
},
{
randomdocid6d7dddd233: {
name: "GHI",
latinName: "JKI"
}
}
];
Beause I dont know the randomdocid's I cant figure out how to display the name and latinName. I have made a codesandbox with the problem to illustrate it: https://codesandbox.io/s/spring-fast-w0tt4?file=/src/App.js:56-268
Im sure it's actually easy to do but I don't seem to be able to figure it out. Hopefully someone knows!
Thanks,
Santi.
You can use Object.keys() as solution here
{data.map((item, index)=> {
let key=Object.keys(item)[0]
return <div key={key}> // better to use unique key value then index
{item[key].latinName}
</div>
)}
You need to first get the key inside every object and return the value of that key in the map. Update the code based on your need to render the data after you fetch it. You can do it like this
export default function App() {
const data = [
{
randomdocid67233: {
name: "ABC",
latinName: "DEF"
}
},
{
randomdocid67233: {
name: "GHI",
latinName: "JKI"
}
}
];
const newData = data.map(item => {
const key = Object.keys(item)[0];
return item[key]
})
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{newData.map((item, index) => (
<div key={index}>
{item.name} {item.latinName}
</div>
))}
</div>
);
}

Replicating nested mapping within a React component

I am struggling with mapping some data so I can properly display it. I have an Object where I have removed a lot of data but the overall structure is like so
{
"userData":[
{
"name":"something",
"job":"something",
}
],
"bikeData":[
{
"id":1,
"userId":1,
"bikesResults": {
"bike_technical":[
[
{
"speed":"28.3mph",
"gears":4,
}
]
],
"top_10_bikes":[
[
{
"name":"Bike1",
"values":3.5,
},
{
"name":"Bike2",
"values":5.4,
},
{
"name":"Bike3",
"values":9.8,
},
{
"name":"Bike4",
"values":4.3,
},
]
],
"bike_score":[
{
"quality":"7",
"price":"3"
}
]
},
"Something":1,
"Somethingelse":0,
}
],
}
So what I am interested in is the bikeData part, more specifically bikesResults and the top_10_bikes. As bikeData is essentially an array of Objects, I used map.
bikeObject.bikeData.map((item, index) => {
console.log(item.bikesResults);
});
So that console.log will output the data for bikesResults, so that seems to work.
The part I am struggling with is the next part, getting the data from the top 10 bikes.
I created an example JSFiddle to show how I got it working with plain Javascript. With React however, I am struggling with the nested maps. Currently I am trying something like this
{bikeObject.bikeData.map((item, index) => {
return item.bikesResults.top_10_bikes.map((item2) => (
{ item2 }
));
})}
And once again, I created a JSFiddle to demonstrate. As you see in this fiddle, in the console, I am getting errors, and not sure how I can even do the third map.
There is probably a better way to do this? But my main goal is to within React, print out the data within top_10_bikes.
Any advice in achieving this appreciated.
Thanks
return (
<div className="App">
<div>
<h2>Data:</h2>
{bikeObject.bikeData.map((item) => {
return item.bikesResults.top_10_bikes.map((item2) => {
return item2.map((item3) => {
return (
<div>
<p>{item3.name}</p>
<p>{item3.values}</p>
</div>
);
});
});
})}
</div>
</div>
);

Categories

Resources