React rendering html elements in nested loops - javascript

I have a data structure like this {key: [array of object]}. I want to render each element in array of object using nested for loop like this:
for each entry(k, v) in map:
for each element in array v:
display html data
I am using react version 16.
I tried this in JSX:
class Positions extends React.Component {
renderPosition(position) {
var expiry = position["ExpiryDay"] + "-" + position["ExpiryMonth"] + "-" + position["ExpiryYear"];
console.log(expiry);
return (<label>{expiry}</label>);
}
render() {
return (
<div>
{this.props.positionsGrouped.forEach(function(positions) {
return (
<div>
{positions.map(function(position) {
return (
<div>
{this.renderPosition(position)}
</div>
);
}.bind(this))}
</div>
);
}.bind(this))}
</div>
);
}
}
Here is the JS that it compiles to:
class Positions extends React.Component {
renderPosition(position) {
var expiry = position["ExpiryDay"] + "-" + position["ExpiryMonth"] + "-" + position["ExpiryYear"];
console.log(expiry);
return React.createElement(
"label",
null,
expiry
);
}
render() {
return React.createElement(
"div",
null,
this.props.positionsGrouped.forEach(function (positions) {
return React.createElement(
"div",
null,
positions.map(function (position) {
return React.createElement(
"div",
null,
this.renderPosition(position)
);
}.bind(this))
);
}.bind(this))
);
}
}
However I don't see anything being rendered except for the top most div. Here is the rendered html:
<div id="app">
<div></div>
</div>
Here is what I see in react developer tools:
<App>
<Positions>
<div></div>
</Positions>
</App>
I don't see any errors in the console. I expected at least three nested divs to be rendered however I only see one so it sounds like something is wrong at the level of the first for loop. But, I do see my expiry variable being printed to console properly so I know renderPosition is getting called with the correct data.
Does anyone know what I am doing wrong? I'm new to react and sorry for any typos. Thanks in advance.

this.props.positionsGrouped.forEach would return undefined. I mean it wouldn't return anything. So nothing gets rendered.

Just change your component code like this
import React from "react";
class Positions extends React.Component {
constructor(props) {
super(props);
this.renderPosition = this.renderPosition.bind(this);
}
renderPosition(position) {
var expiry = position["name"] + "-" + position["title"];
console.log(expiry);
return <label>{expiry}</label>;
}
render() {
const { positionsGrouped } = this.props;
return (
<div>
{positionsGrouped.map(positions => {
const keys = Object.keys(positions);
return (
<div>
{positions[keys[0]].map(position => {
return <div>{this.renderPosition(position)}</div>;
})}
</div>
);
})}
</div>
);
}
}
export default Positions;
Inside your parent file
import React from "react";
import ReactDOM from "react-dom";
import Position from "./test";
import "./styles.css";
function App() {
var positionGroup = [
{
a: [
{
name: "hello",
title: "sdfd"
},
{
name: "hello",
title: "sdfd"
},
{
name: "hello",
title: "sdfd"
}
]
},
{
b: [
{
name: "hello",
title: "sdfd"
},
{
name: "hello",
title: "sdfd"
},
{
name: "hello",
title: "sdfd"
}
]
}
];
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Position positionsGrouped={positionGroup} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

The return value of forEach is undefined no matter what you return in callback function. use map instead.
class Positions extends React.Component {
getExpiry(position) {
return `${position.ExpiryDay}-${position.ExpiryMonth}-${position.ExpiryYear}`;
}
render() {
return (
<div>
{this.props.positionsGrouped.map(positions => (
<div>
{positions.map((position) => (
<div>
<label>{this.getExpiry(position)}</label>
</div>
))}
</div>
))}
</div>
);
}
}
I changed your code a little to make it more concise.

Related

React - Render children in matching sort order?

Given a component that renders its children, I can't get the children to render sorted as per their newOrder order:
export default class EnhancedLinks extends React.Component {
render() {
return (
<div>
{React.Children.map(
this.props.children.filter((c) => c),
(el) => el
)}
</div>
);
}
}
export default class App extends React.Component {
render() {
const newOrder = ["dandelion", "cantaloupe", "apple", "banana"];
return (
<div>
<EnhancedLinks>
<div name="apple" color="red">apple</div>
<div name="banana" color="yellow">banana</div>
<div name="cantaloupe" color="orange">cantaloupe</div>
<div name="dandelion" color="green">dandelion</div>
</EnhancedLinks>
</div>
);
}
}
Any idea how to get the EnhancedLinks children to render as per the order of the newOrder array?
Here's a fiddle:
https://codesandbox.io/s/react-and-scss-forked-z1p0b?file=/src/index.js
Map the newOrder array to <div>s instead of writing them out individually?
const colors = ['red', 'yellow', 'orange', 'green'];
return (
<div>
<EnhancedLinks>
{newOrder.map((name, i) => <div name={name} color={colors[i]}>{name}</div>)}
</EnhancedLinks>
</div>
);
The
Your EnchancedLinks component should render the div, color and text, not the outside wrapping component. This way there's less copy/pasted code and you can set the order in your array, or manipulate your array as you need to.
export default class EnhancedLinks extends React.Component {
render() {
return (
<div name={this.props.name} color={this.props.color}>
{this.props.name}
</div>
);
}
}
export default class App extends React.Component {
render() {
const newOrder = [
{
name: "dandelion",
color: "green"
},
{
name: "cantaloupe",
color: "orange"
},
{
name: "apple",
color: "red"
},
{
name: "banana",
color: "yellow"
}];
return (
<div>
{newOrder.map((link) => {
return <EnhancedLinks {...link} />
})}
</div>
);
}
}
I've forked your fiddle with a solution I've come up with: https://codesandbox.io/s/react-and-scss-forked-c1r1f

React check the elements of an array for a conditional display

I would like to check if the value of my element appears in
an array if it is the case I give it the class
another class.
this is to make a map from another object array
How to check in the whole table if
Is there the value I want?
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
class Dbz extends React.Component {
constructor(props) {
super(props)
This.state = {
sayien = ['goku','vegeta','broly']
warrioz = [
{ name:goku
power: 1500
},
{ name: yamcha
power: 150
},
{ name: cell
power: 2500
},
]
}
}
render(){
return(
<div>
{ this.state.warrioz.map((data) => {
return (
<div className={this.state.sayien === data.name ? "sayien" :"nosayien"}>
<p>{data.name} </p>
</div>
})}
</div>
)
}
}
export default Dbz
You can see if data.name is included in your state. But the question remains, where is data coming from?
<div className={this.state.sayien.includes(data.name) ? "sayien" :"nosayien"}>
<p>goku </p>
</div>
If you are curious here is a link to the mdn doc for includes.

Need to Trigger individual Element in an array of elements written through map function reactjs

class Services extends Component {
constructor(props) {
super(props);
this.state = {showoffer: false};
}
showOffers=( )=>{
this.setState({showoffer: !this.state.showoffer});
}
render() {
return (
<div className="OSServicesContainer">
<img className="OSlogomark" src={logomark} alt="logo mark" />
<article className="OssHeadingText">OOM INTERIORS OFFERS</article>
{offersdata.map((offers,index)=>{
return ( <div key={index} className="OssoffersContainermain">
<div className="OssoffersContainer">
<div className="OssofferHeadingmain">
<article className="OssofferHeading">{offers.heading}</article>
</div>
<article className="OssofferText">{offers.subheading}</article>
<div className="OssofferViewbtnmain">
<article key={index} className="OssofferViewbtn" onClick={this.showOffers}>{this.state.showoffer?"View Less":"View More"}</article>
</div>
</div>
{!this.state.showoffer?
null:
<div className="OssOfferSubCompmain">
{offers.offersub.map((offer,key) =>{
return <OssOfferSubComp ofrtext={offer.text} ofrsubtext={offer.subtext} />
})}
</div>}
</div>
)
})}
</div>);
}
}
export default Services;
Above is my code
i want to call showoffer function and update only that element clicked
please what shall i do it is triggering all elements
how to trigger single element??
You can try something like this:
`class Services extends Component {
constructor(props) {
super(props);
this.state = {showoffer: 0};
}
showOffers = ( offerIndex ) => {
this.setState({showoffer: offerIndex});
}
hideOffers = () => {
this.setState({showoffer: 0});
}
render() => {
...
<div className="OssofferViewbtnmain">
<article key={index} onClick={ () => this.showOffers(index) }>
{this.state.showoffer?"View Less":"View More"}
</article>
</div>
...
{
this.state.showOffer && this.state.showOffer === index
? // then show it
: ''
}
}`
Hey if you wish to have multiple items open at the same time you can do something like this where you mutate the mapped item to track show hide state. I have added a visible property to the list item that keeps track if the item is open or closed:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends Component {
state = {
items: [
{ header: "Test 1", extra: "Some extra content A" },
{ header: "Test 2", extra: "Some extra content B" },
{ header: "Test 3", extra: "Some extra content C" }
]
};
onItemClick(index) {
const selected = this.state.items[index];
this.setState({
items: [
...this.state.items.slice(0, index),
{ ...selected, visible: !selected.visible },
...this.state.items.slice(index + 1)
]
});
}
render() {
return (
<div>
<ul>
{this.state.items.map((item, index) => {
return (
<li
key={index}
style={{ cursor: "pointer" }}
onClick={() => this.onItemClick(index)}
>
<h3>{item.header}</h3>
{item.visible ? <div>{item.extra}</div> : null}
</li>
);
})}
</ul>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/busy-germain-hdmrn

I can't implement a Lightbox Gallery on React

I'm follow the steps of this dependencie:
http://jossmac.github.io/react-images/
And it isn't work. No picture showing and there is showing an error message:
index.js:2178 Warning: Failed prop type: The prop onClose is marked
as required in Lightbox, but its value is undefined
Here is my code:
import React, { Component } from "react";
import Lightbox from "react-images";
const URL_INTERIORES = "http://localhost:3001/interiores";
const LIGHTBOX_IMAGE_SET = [
{
src: "/images/int_02.jpg",
caption: "A forest",
// As an array
srcSet: ["/images/int_02.jpg", "/images/int_02.jpg"]
},
{
src: "/images/int_02.jpg",
// As a string
srcSet: "/images/int_02.jpg 1024w, /images/int_02.jpg 800w, /images/int_02.jpg 500w, /images/int_02.jpg 320w"
}
];
class Interiores extends Component {
render() {
const { open } = this.state;
return (
<div>
<div>
<Lightbox
images={LIGHTBOX_IMAGE_SET}
isOpen={this.state.lightboxIsOpen}
onClickPrev={this.gotoPrevLightboxImage}
onClickNext={this.gotoNextLightboxImage}
onClose={this.closeLightbox}
/>
</div>
</div>
);
}
}
export default Interiores;
Does anybody know how to solve it? Tahnk you
Consider adding all the missing handlers & state in your class:
class Interiores extends Component {
state = {
lightboxIsOpen: false
}
gotoPrevLightboxImage() {
// Add the logic here
}
gotoNextLightboxImage() {
// Add the logic here
}
closeLightbox(e) {
// Add the logic here
}
render() {
const { lightboxIsOpen } = this.state;
return (
<div>
<Lightbox
images={LIGHTBOX_IMAGE_SET}
isOpen={lightboxIsOpen}
onClickPrev={() => this.gotoPrevLightboxImage()}
onClickNext={() => this.gotoNextLightboxImage()}
onClose={e => this.closeLightbox(e)}
/>
</div>
);
}
}

Nested React list not working

I am trying to recursively render JSON data to nested list using React. Right now I am using simple data object like this:
[{"id": "1",
"name": "Luke"
},
{"id": "2",
"name": "Jim",
"childNodes":[{
"id": "3",
"name": "Lola"
}]
}]
using this class:
export default class NestedList extends Component {
constructor(props) {
super(props);
this.state = {
visible: true
};
}
toggle = () => {
this.setState({ visible: !this.state.visible });
};
renderChild = (child) => {
if (child.childNodes) {
return (
<ul>
{child.myData.map(item => {
return this.renderChild(item);
})}
</ul>
);
}
else if (child.name) {
return <input type="checkbox"><Child name={child.name}/></input>;
}
return null;
}
render() {
return (
<aside>
<div>
<h4>Data Sets</h4>
<ul>
{this.renderChild(this.props.myData)}
</ul>
</div>
</aside>
);
}
}
which calls a Child class that creates list element:
export default class Child extends Component {
render() {
let {name}=this.props;
return (
<li>{name}</li>
);
}
}
but it doesn't print anything. I have tried removing attribute childNodes altogether and tried to print the list but it doesn't work still. I don't understand where I am doing wrong. I would appreciate some help regarding how to fix this.
You need to map through myData first so the rendering process begins:
<ul>
{this.props.myData.map(data => this.renderChild(data))}
</ul>
Also, on childNodes you need to loop through child.childNodes:
if (child.childNodes) {
return (
<ul>
{child.childNodes.map(node => this.renderChild(node))}
</ul>
);
}
there were couple of issues here:
You passed myData to renderChild which doesn't hold childNodes
property nor name property. Hence none of the conditions were met
(null was returned).
So maybe you should loop through myData and
pass each member of the array to renderChild.
Even if we will pass a valid "child" to the renderChild method,
inside this condition:
if (child.childNodes) {
Again you are using a wrong property:
<ul>
{child.myData.map(item => {
return this.renderChild(item);
})}
</ul>
this should be:
{child.childNodes.map(item => {...
Last thing, You can't nest child elements inside an input element.
so change the layout, maybe like this? :
<input type="checkbox"/>
<Child name={child.name} />
Here is a running example with your code:
const data = [
{
id: "1",
name: "Luke"
},
{
id: "2",
name: "Jim",
childNodes: [
{
id: "3",
name: "Lola"
}
]
}
];
class NestedList extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: true
};
}
toggle = () => {
this.setState({ visible: !this.state.visible });
};
renderChild = child => {
if (child.childNodes) {
return (
<ul>
{child.childNodes.map(item => {
return this.renderChild(item);
})}
</ul>
);
} else if (child.name) {
return (
<div>
<input type="checkbox"/>
<Child name={child.name} />
</div>
);
}
return null;
};
render() {
return (
<aside>
<div>
<h4>Data Sets</h4>
<ul>{this.props.myData.map(item => this.renderChild(item))}</ul>
</div>
</aside>
);
}
}
class Child extends React.Component {
render() {
let { name } = this.props;
return <li>{name}</li>;
}
}
ReactDOM.render(<NestedList myData={data} />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Categories