Iterating over JSON in React - javascript

I have following code:
export class Highlights extends React.Component {
render() {
return (
<div>
{JSON.stringify(this.props.highlights_data.data)}
</div>
)
}
}
This prints out the following:
{"active":{"label":"Active","value":"12"},"automatic":{"label":"Automatic","value":"8"},"waiting":{"label":"Waiting","value":"1"},"manual":{"label":"Manual","value":"3"}}
How can I iterate over the highlights_data.data props to call another Component passing down label and value ?

Except for #Dan's answer, I don't believe the other answers are any helpful/useful to you as they don't iterate through your JSON object.
To do this properly, you would need to iterate through each of your keys in your JSON object. There are a few ways you can do this, one of which is with Object.keys(). Like the code snippet below.
This solution iterates through each key in your JSON object and pushes it into an array. Once you have that array, you can iterate through it with map(), as you would normally, and pass your relevant props down to another child component.:
class MyApp extends React.Component {
render() {
var json = {"active":{"label":"Active","value":"12"},"automatic":{"label":"Automatic","value":"8"},"waiting":{"label":"Waiting","value":"1"},"manual":{"label":"Manual","value":"3"}};
var arr = [];
Object.keys(json).forEach(function(key) {
arr.push(json[key]);
});
return <ul>{arr.map(item => <MyAppChild key={item.label} label={item.label} value={item.value} />)}</ul>;
}
}
class MyAppChild extends React.Component {
render() {
return <li>{this.props.label + " - " + this.props.value}</li>;
}
}
ReactDOM.render(<MyApp />, document.getElementById('myapp'));
<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="myapp"></div>

export class Highlights extends React.Component {
render() {
const { data } = this.props.highlights_data;
return (
<div>
{
Object.keys(data).map((e, i) => {
<SomeComponent key={i} {...e} />
})
}
</div>
)
}
}

<div>
{this.props.highlights_data.data.map((e, i) =>
<SomeComponent key={i} label={e.label} value={e.value} />
)}
</div>
You could just send in the item itself.
<SomeComponent key={i} item={e} />
And access label and value in the child with props.item.label or props.item.value.

//let myJSON={"attr1":"abcdef", "attr2":"12345", "attr3":"hello"};
<p>
{Object.keys(myJSON).map((innerAttr, index) => {
return (
<span key={index}> {innerAttr}: {myJSON[innerAttr]}<br/></span>
)})
}
</p>

var Highlight = React.createClass({
render: function() {
const {value, label} = this.props;
return <div>{label}: {value}</div>;
}
});
var Highlights = React.createClass({
render: function() {
const {active, automatic, waiting, manual} = this.props.highlights_data.data;
return (
<div>
<Highlight {...active} />
<Highlight {...automatic} />
<Highlight {...waiting} />
<Highlight {...manual} />
</div>
);
}
});
const data = {data:{"active":{"label":"Active","value":"12"},"automatic":{"label":"Automatic","value":"8"},"waiting":{"label":"Waiting","value":"1"},"manual":{"label":"Manual","value":"3"}}};
ReactDOM.render(
<Highlights highlights_data={data} />,
document.getElementById('container')
);

Related

How to autoincrement the index and print the array values in render?

I have an array of names and I need to loop through the index and print the names in render
const names = ['John','Sara','Michael','Timothy']`
render: (props) => ({
<div>
props=names[];
</div>
});
You yan use for ... in loop to iterate through indexes.
const names = ['John','Sara','Michael','Timothy'];
for(const index in names) {
console.log(`${index} of ${names[index]}`);
}
const names = ["John", "Sara", "Michael", "Timothy"];
class Content extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<h1>Names</h1>
{this.props.names ? (
this.props.names.map((name, index) => (
<p key={name + index}>{name}</p>
))
) : (
<p>No names found</p>
)}
</div>
);
}
}
ReactDOM.render(<Content names={names} />, document.getElementById("app"));
<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>
<div id="app"> </div>
You have to improve the part of your code. It doesn't seem like a JSX part. Here, how I suppose it can be:
render() {
const names = ['John','Sara','Michael','Timothy'];
return <div>
{names.map((item, index) => (
<div key={index}>
{item}
</div>
))}
</div>;
}
You can use map() to accomplish your demand.
render() {
const names = ['John','Sara','Michael','Timothy'];
return (
<div>
{ names.map((name, index) => <div key={index}>{ name }</div> }
</div>
);
}

React - How to return a component with a dynamic name?

I am trying to return a component without a set name at runtime. Like so:
<div className="project-demo">
<CustomComponent demo={project.demo}/>
</div>
and being called like this:
const CustomComponent = ({ demo }) => {
return (
<{ demo } />
)
}
Any advice?
JSX expects components to have capitalized names
const CustomComponent = ({ demo }) => {
const Demo = demo;
return (
<Demo />
)
}
or better:
const CustomComponent = ({ Demo }) => {
return (
<Demo />
)
}

Using dynamic onClick with ref

Passing a dynamic property of onClick= do something by the use of ref gives me back: TypeError: _this.listReference is null listReference is defined in one of my components that i will show below.
In Component #1
class Component1 extends Component {
constructor(props){
super(props)
this.listReference= null;
}
//Returns
<div>
<SomeComponent list={(ref) => this.listReference= ref} />
<Component2 onMarkerClick = {(index) => {
this.listReference.scrollTop = 48 * index
}}/>
In Component #2
render() {
const {classes, driversStore, onMarkerCLick} = this.props
...
{driversStore.sortedSelectedOrders.map((order , index) => {
return (
<Component3
onClick={ () => onMarkerClick(index)} />
In Component #3
render() {
const { onClick } = this.props;
return (
<div
onClick={onClick}>
I expect upon click to trigger the scroll functionality (as Stated in Component #1).
Thanks in advance!
Check this example. Hope it can help you!
const Component2 = (props) =>(
<button onClick={props.onClick}>click me</button>
);
const SomeCompo = (props) =>(
<div>SomeComponent</div>
);
class Component1 extends React.Component{
listReference = React.createRef();
render(){
return(
<div>
<SomeCompo list={this.listReference}>reference</SomeCompo>
<Component2 onClick={this.handleClick} />
</div>
);
}
handleClick = () => {
if(this.listReference){
this.listReference={scrollTop:100};
}
console.log(this.listReference)
}
}
ReactDOM.render(<Component1/>,document.getElementById("root"));
<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>
<div id="root"></div>
You should do the following in constructor,
this.listReference = React.createRef()

How to hide all the div while showing the one which is clicked, in React?

I'm generating some identical div through a list. Below is the sample code.
I'm toggling this div
class App extends React.Component {
state = { showKitten: false };
handleToggleKitten = () => {
this.setState((prevState, props) => ({
showKitten: !prevState.showKitten,
}));
};
render() {
return (
<About
data={datalist}
showKitten={this.state.showKitten}
handleToggleKitten={this.handleToggleKitten}
/>
);
}
}
const About = ({ datalist, showKitten, handletogglekitten }) => {
return (
<div>
{datalist.map((item, index) => {
return (
<div key={index}>
<div onClick={handletogglekitten} />
showKitten ? <div /> : null
</div>
);
})}
</div>
);
};
I have defined tooglefunction and the flag state variable in parent and passing them to children and in children component, I'm creating this divs by iterating over a list. Right now I am able to achieve the toggle functionality for the individual div set but I want to hide all the div and show the one which is clicked.
You could use the index value. Here's a working example.
const datalist = ["cat 1", "cat 2", "cat 3"];
class App extends React.Component {
state = { showKittenIndex: null };
render() {
return (
<About
datalist={datalist}
showKittenIndex={this.state.showKittenIndex}
toggleKitten={index => this.setState({ showKittenIndex: index })}
/>
);
}
}
const About = ({ datalist, showKittenIndex, toggleKitten }) => (
<div className="about">
{datalist.map((item, index) => (
<div key={index}>
<button onClick={() => toggleKitten(index)}>toggle {index}</button>
{showKittenIndex === index && <div>{item}</div>}
</div>
))}
</div>
);
I have a very similar approach than #Kunukn.
But I don't see the need to wrap it in a functional component.
import React, { Component } from 'react';
const elements = ['DIV #1', 'DIV #2', 'DIV #3', 'DIV #4', 'DIV #5', 'DIV #6'];
class App extends Component {
constructor(props) {
super(props);
this.state = {
activeElement: null,
allElements: elements,
};
}
render() {
return (
<About
elements={this.state.allElements}
showIndex={this.state.activeElement}
toggleIndex={index => this.setState({ activeElement: index })}
/>
);
}
}
const About = ({ elements, showIndex, toggleIndex }) => (
<div className="about">
{elements.map((element, index) => (
<div key={index}>
<div onClick={() => toggleIndex(index)}>toggleIndex {index}</div>
{showIndex === index && <div>{element}</div>}
</div>
))}
</div>
);
export default App;
I did write a little clickHandler ... I know that it is not needed at the moment, but when you would want to alter the data received with the click-event this could be handled there as well.
EDIT
According to the comment I improved the code a bit by making a functional component showing the DIVs. I did also dismiss the clickHandler() function.

How to render html string

I have a server response which contains an html string which is passed to a react component as a prop. Within the html there are codes which need to be replaced with React components.
I've used react-string-replace to get this to work but it doesn't seem to work with HTML as the tags are escaped by React. Does anyone know how this might be fixed?
import React from 'react';
import replace from 'react-string-replace';
const reg = /\{(name)\}/g;
const Name = props => {
return (
<div>Hello {props.name}</div>
)
}
class Embed extends React.Component {
render() {
const person = this.props.person
const component = <Name name={person.name} key={person.id} />;
const output = replace(
this.props.content,
reg,
prop => component
);
return (
<div>{output}</div>
)
}
}
const Greeting = props => {
return <Embed content="<div><h1>Greetings</h1> <strong>{name}</strong></div>" person={{ name: 'John', id: 123 }} />;
};
export default Greeting;
Try this -
class Embed extends React.Component {
render() {
const person = this.props.person
const component = <Name name={person.name} key={person.id} />;
const output = replace(
this.props.content,
reg,
prop => component
);
return (
<div dangerouslySetInnerHTML={{ __html: output }}></div>
)
}
}
I suggest much better way to do it like below -
const reg = /\{(name)\}/g;
const Name = props => {
return (
<div>Hello {props.name}</div>
)
}
class Embed extends React.Component {
render() {
const person = this.props.person;
const component = <Name name={person.name} key={person.id} />;
return (
<div><h1>Greetings</h1> <strong>{component}</strong></div>
);
}
}
const Greeting = props => {
return (<Embed person={{ name: 'John', id: 123 }} >
</Embed>);
};
ReactDOM.render(
<Greeting/>,
document.getElementById('test')
);
<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="test">
</div>
Wants to remind you this:
From Facebook React Doc:
dangerouslySetInnerHTML is React's replacement for using innerHTML in
the browser DOM. In general, setting HTML from code is risky because
it's easy to inadvertently expose your users to a cross-site scripting
(XSS) attack. So, you can set HTML directly from React, but you have
to type out dangerouslySetInnerHTML and pass an object with a __html
key, to remind yourself that it's dangerous.
Try this:
const Name = props => {
return (
<div>
Hello {props.name}
</div>
)
}
class Embed extends React.Component {
render() {
let content = this.props.content.replace('{name}', this.props.person.name);
return (
<div>
<Name person={this.props.person}/>
<div dangerouslySetInnerHTML={{ __html: content}}></div>
</div>
)
}
}
const Greeting = props => {
return <Embed content="<div><h1>Greetings</h1> <strong>{name}</strong></div>" person={{ name: 'John', id: 123 }} />;
};
ReactDOM.render(<Greeting />, document.getElementById('container'));
Check working example on jsfiddle: https://jsfiddle.net/h81q9nqd/

Categories

Resources