Replicating nested mapping within a React component - javascript

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>
);

Related

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>
);
}

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

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 :)

Mapping through array of objects to display images

I'm trying to map through an array of objects to display the images. Here is my code:
import React from 'react';
import photos from '../photo-store';
class Landing extends React.Component {
render() {
const photoDisplay = Object.keys(photos).map((photo, i) => {
return <img key={i} src={`.${photos[photo][i].src}`} alt='headshot'/>
})
console.log('photoDisplay', photoDisplay)
return (
<div>
<p>Photos will go here</p>
{photoDisplay}
</div>
)
}
}
export default Landing;
The src value is correct when I console.log, but for some reason I'm just getting my alt information rendering, and it's not going through all of the objects in the array. Any pointers on what might be happening here would be awesome. Thanks in advance for your help!
Here is a snippet of what is in "photos":
"photos": [
{
id: 1,
name: "AmberB",
src: "./images/AmberB.jpg"
},
{
id: 2,
name: "AmberR",
src: "./images/AmberR.jpg"
}
]
}
You made a small mistake in the return statement. If you have for src attribute the ${photos[photo].src} instead of photos[photo][i].src then it should work.
const photoDisplay = Object.keys(photos).map((photo, i) => {
return <img key={i} src={`${photos[photo].src}`} alt='headshot'/>
})
Please also consider removing the . as well but not sure about that.
I hope that helps!

Dynamic layout of React component from JSON

I am writing a react application that is a thin client UI for a financial trading application. A core requirement is that the application be completely dynamic and configurable, including forms. Specifically, I have trade entry forms that need to be defined on the server side and stored in the database to be rendered dynamically on the client but the layout is important and needs to be able to support multiple different formats. I have seen a few libraries that take JSON form schemas and create static forms from them but none of them seem to support the kind of layout flexibility I need. For example, I need to support tabs, columns, and rows of components. My question is - can anyone suggest a ReactJs library that can do what I'm looking for? If not, how might I go about implementing it myself?
Here's a more concrete example; Suppose I have a schema fetched from the server via a REST call that looks something like this:
{
title: "Securities Finance Trade Entry",
children: [
{
containerType: "tabs",
children: [
{
title: "Common",
children: [
{
containerType: "row",
children: [
{
input: "ComboBox",
label: "Trade Type",
options: ["Repo", "Buy/Sell", "FeeBased"]
},
{
input: "ComboBox",
label: "Direction",
options: ["Loan", "Borrow"]
}
]
},
{
containerType: "row",
children: [
{
containerType: "column",
children: [
{
containerType: "row",
children: [
{
input: "text",
label: "Book"
},
{
input: "text",
label: "Counterparty"
}
]
},
{
containerType: "row",
children: [
{
input: "date",
label: "StartDate"
},
{
input: "date",
label: "EndDate"
}
]
},
{
containerType: "row",
children: [
{
input: "text",
label: "Security"
},
{
input: "numeric",
label: "Quantity"
}
]
}
]
}
]
}
]
}
]
}
]
}
Which I expect to render something like:
Basically in that schema only one tab would be shown, but there could be multiple tabs, each containing multiple children in rows and columns and potentially nested containers of tabs too. If I were to render this myself in react I would think about using .map to iterate through the json and a number of if statements to insert tags where appropriate. However, items need to be nested so I don't know how to render it such that the tag chosen is dynamic and it can have children... For example I could write:
{ if (container.containerType === "column") { () } but then I'd somehow need to embed the rest of the controls inside that tag, I don't think I could just emit a () at the end...
Another option I've considered is translating the above json to JSX on the server side and sending that. It would be fairly easy to write a parser on the Java server side that converts the above json to a JSX document and return that to the client, but then how would I render it? Is there any way I could do something like:
onComponentMount() {
fetch(webserviceUrl + 'getJsxForForm/' + props.formName)
.then(result => {this.setState({form : result});
}
render() {
return ({this.state.form});
}
But again, I don't think this will work. If I fetch the document from the server it would render it just as plain text and not actually convert it to valid html, right?
So, what are my options? I'm looking for suggestions of an existing library that would do this, or suggestions on either of the other two approaches that I'm mentioned (would they work?, how could I do it?), or alternative ideas.
Thanks,
Troy
I love the concept of dynamically rendering pages from some sort of JSON configuration.
The key will be defining Components to match containerTypes and inputs and then traversing your JSON configuration through a recursive function. In your JSON configuration, I suggest using component naming conventions wherever you want a component to be rendered. Hence, capitalizing Tabs, Row, Column, etc
Here is one example of that function. Note, in each of the containerType Components there is a call to this function with children being passed in.
See this pen: https://codepen.io/wesleylhandy/pen/oQaExK/
Example Component:
const Container = props => {
return (
<div className="container">
<h1>{props.title}</h1>
{renderChildren(props.children)}
</div>
)
}
Example Recursive-ish rendering of children
const renderChildren = children => {
return children ? children.map((child, ind) => {
const newChildren = child.children ? [...child.children] : [];
const {containerType, title, input, label, options} = child
let key;
if (newChildren.length) {
key = `${containerType}-${ind}`;
switch (containerType) {
case "Tabs":
return <Tabs
key={key}
title={title}
children={newChildren}
/>
case "Column":
return <Column
key={key}
title={title}
children={newChildren}
/>
case "Row":
return <Row
key={key}
title={title}
children={newChildren}
/>
default:
return <Common
key={key}
title={title}
children={newChildren}
/>
}
} else {
key=`${input}-${ind}`
switch (input) {
case "ComboBox":
return <SelectGroup
key={key}
label={label}
options={options}
/>
case "Text":
case "Date":
case "Numeric":
return <InputGroup
key={key}
label={label}
type={input}
/>
}
}
}) : null
}

Rendering a object onto a React component

I thought this would be a simple task, but I've been working on this all day but still can't seem to figure it out.
I am receiving a very large (multiple layers of objects) JSON file which I stored in a state of my component, now I need to render that data on the screen. This has become difficult, because within the object I have several others objects which also may contain other objects.
So far, I am using Object.keys(myJSONObject).map(...) to try to get it done, however I can't seem to find a way to reach all the 'sub-objects'. Here is my current code:
render: function(){
return (
<div>
{
Object.keys(_this.state.content).map(function (key) {
if (typeof _this.state.content[key] instanceof Object){
//go through all objects and sub-objects???
}
return <div > Key: {
key
}, Value: {
_this.state.content[key]
} </div>;
})
}
</div>
);
}
Edit: I should probably add that my object is _this.state.content
Edit 2: Here is an example of the object I am looking to iterate through. Keep in mind that is it a lot bigger than this.
{ "3.8": [ "Something something" ],
"3.2": [ { "Blabla": [ "More things I am saying", "Blablablabal", "Whatever" ] } ],
"2.9": [ { "Foo": [ "bar", "something something something something", "blablablabalbalbal" ] } ]}
Edit 3: Here is how I would somewhat like it to look when rendered:
3.8:
- Something something
3.2:
- Blabla:
- More things I am saying
- Blablablabal
- Whatever
2.9:
-Foo:
-bar
...
Is this what your are after: http://codepen.io/PiotrBerebecki/pen/PGjVxW
The solution relies on using React's reusable components. It accepts objects of varying levels of nesting as per your example. You can adjust it further to accommodate even more types of objects.
const stateObject = {
"3.8": [ "Something something" ],
"3.2": [ { "Blabla": [ "More things I am saying", "Blablablabal", "Whatever" ] } ],
"2.9": [ { "Foo": [ "bar", "something something something something", "blablablabalbalbal" ] } ]
}
class App extends React.Component {
render() {
const renderMainKeys = Object.keys(stateObject)
.map(mainKey => <MainKey mainKey={mainKey}
innerObject={stateObject[mainKey]} />);
return (
<div>
{renderMainKeys}
</div>
);
}
}
class MainKey extends React.Component {
render() {
if (typeof this.props.innerObject[0] === 'string') {
return (
<div>
<h4>{this.props.mainKey}</h4>
<ul>
<li>{this.props.innerObject[0]}</li>
</ul>
</div>
);
}
const innerObjectKey = Object.keys(this.props.innerObject[0])[0];
const innerList = this.props.innerObject[0][innerObjectKey];
return (
<div key={this.props.mainKey}>
<h4>{this.props.mainKey}</h4>
<InnerKey innerObjectKey={innerObjectKey} innerList={innerList}/>
</div>
)
}
}
class InnerKey extends React.Component {
render() {
return (
<ul>
<li>{this.props.innerObjectKey}</li>
<InnerList innerList={this.props.innerList} />
</ul>
)
}
}
class InnerList extends React.Component {
render() {
if (!Array.isArray(this.props.innerList)) {
return (
<ul>
<li>{this.props.innerList}</li>
</ul>
);
}
const listItems = this.props.innerList.map(function(item, index) {
return <li key={index}>{item}</li>;
});
return (
<ul>
{listItems}
</ul>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
Here is a code which I wrote sometime back to handle 3 layers of nesting in my json file.
JSON
var a = {
"parent":{
"name":"x",
"child":{
"name":"y",
"subchild":{
"name":"check"
}
}
}
}
Iterator
Object.keys(obj).map(function(key,index){
let section = obj[key]
//getting subsections for a single section
let subSections = section["subsections"] // get you nested object here
Object.keys(subSections).map(function(subSectionId,key){
//getting a single sub section
let subSection=subSections[subSectionId]
//getting instruments for a sub section
let nestedSection = subSection["//key"] //get you next nested object here
Object.keys(instruments).map(function(instrumentId,key){
//operation
}
})
})
})
})
Hope it helps.

Categories

Resources