how to parse loop for json in react js - javascript

I am new to react.
this.state = { histories: [
{
"qas":[
{"question": "hi1", "answer": "hello1"},
{"question": "hi2", "answer": "hello2"}
]
}
] };
render(){
return (
<div>
<History
histories={this.state.histories} />
</div>
);
}
In separate component page, I would like to use react js to render question and answer by loop or map, however I tried map, it didn't recognize map. I have tried for loop, but it didn't get the child attribute from it.
const history = ({histories}) => {
return(
<div>
{histories[0].qas[0].question}
</div>
<div}>
{histories[0].qas[0].answer}
</div>
);
}

Here is an example with map, hope it will help.
const History = ({histories}) => {
// Quick, hacky way to set key.
// More on keys in React https://facebook.github.io/react/docs/lists-and-keys.html#keys
let key = 1;
const questionsAndAnswers = histories[0].qas.map(child =>
<div key={key++}>
<div>{child.question}</div>
<div>{child.answer}</div>
</div>
);
return (
<div>{questionsAndAnswers}</div>
);
};
class Histories extends React.Component {
constructor(props) {
super(props);
this.state = {
histories: [
{
"qas":[
{"question": "hi1", "answer": "hello1"},
{"question": "hi2", "answer": "hello2"}
]
}
]
};
}
render() {
return(
<div>
<History histories={this.state.histories}/>
</div>
)
}
}
ReactDOM.render(
<Histories/>,
document.getElementById("history")
);
<div id="history"></div>
<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>
If you remove the “div” from the <div>{questionsAndAnswers}</div>, then you’ll get the error you encountered “A valid React element (or null)…”. If you want to render multiple elements you need to wrap them in a div. More on this https://facebook.github.io/react/docs/jsx-in-depth.html#jsx-children

It does not recognize this histories, because I bet they are undefined at your start.
const history = ({histories}) => {
if (!histories || histories.length < 1) return (<div>nothing</div>);
return histories.map(v => (<div>JSON.stringify(v)</div>))
}
Another problem could be this.state.roundshistories. It is undefined in your example.

Related

Not rendering JSX from function in React

The function is getting the value of a button click as props. Data is mapped through to compare that button value to a key in the Data JSON called 'classes'. I am getting all the data correctly. All my console.logs are returning correct values. But for some reason, I cannot render anything.
I've tried to add two return statements. It is not even rendering the p tag with the word 'TEST'. Am I missing something? I have included a Code Sandbox: https://codesandbox.io/s/react-example-8xxih
When I click on the Math button, for example, I want to show the two teachers who teach Math as two bubbles below the buttons.
All the data is loading. Just having an issue with rendering it.
function ShowBubbles(props){
console.log('VALUE', props.target.value)
return (
<div id='bubbles-container'>
<p>TEST</p>
{Data.map((item,index) =>{
if(props.target.value == (Data[index].classes)){
return (
<Bubble key={index} nodeName={Data[index].name}>{Data[index].name}
</Bubble>
)
}
})}
</div>
)
}
Sandbox Link: https://codesandbox.io/embed/react-example-m1880
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
const circleStyle = {
width: 100,
height: 100,
borderRadius: 50,
fontSize: 30,
color: "blue"
};
const Data = [
{
classes: ["Math"],
name: "Mr.Rockow",
id: "135"
},
{
classes: ["English"],
name: "Mrs.Nicastro",
id: "358"
},
{
classes: ["Chemistry"],
name: "Mr.Bloomberg",
id: "405"
},
{
classes: ["Math"],
name: "Mr.Jennings",
id: "293"
}
];
const Bubble = item => {
let {name} = item.children.singleItem;
return (
<div style={circleStyle} onClick={()=>{console.log(name)}}>
<p>{item.children.singleItem.name}</p>
</div>
);
};
function ShowBubbles(props) {
var final = [];
Data.map((item, index) => {
if (props.target.value == Data[index].classes) {
final.push(Data[index])
}
})
return final;
}
function DisplayBubbles(singleItem) {
return <Bubble>{singleItem}</Bubble>
}
class Sidebar extends Component {
constructor(props) {
super(props);
this.state = {
json: [],
classesArray: [],
displayBubble: true
};
this.showNode = this.showNode.bind(this);
}
componentDidMount() {
const newArray = [];
Data.map((item, index) => {
let classPlaceholder = Data[index].classes.toString();
if (newArray.indexOf(classPlaceholder) == -1) {
newArray.push(classPlaceholder);
}
// console.log('newArray', newArray)
});
this.setState({
json: Data,
classesArray: newArray
});
}
showNode(props) {
this.setState({
displayBubble: true
});
if (this.state.displayBubble === true) {
var output = ShowBubbles(props);
this.setState({output})
}
}
render() {
return (
<div>
{/* {this.state.displayBubble ? <ShowBubbles/> : ''} */}
<div id="sidebar-container">
<h1 className="sidebar-title">Classes At School</h1>
<h3>Classes To Search</h3>
{this.state.classesArray.map((item, index) => {
return (
<button
onClick={this.showNode}
className="btn-sidebar"
key={index}
value={this.state.classesArray[index]}
>
{this.state.classesArray[index]}
</button>
);
})}
</div>
{this.state.output && this.state.output.map(item=><DisplayBubbles singleItem={item}/>)}
</div>
);
}
}
ReactDOM.render(<Sidebar />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
The issue here is ShowBubbles is not being rendered into the DOM, instead (according the sandbox), ShowBubbles (a React component) is being directly called in onClick button handlers. While you can technically do this, calling a component from a function will result in JSX, essentially, and you would need to manually insert this into the DOM.
Taking this approach is not very React-y, and there is usually a simpler way to approach this. One such approach would be to call the ShowBubbles directly from another React component, e.g. after your buttons using something like:
<ShowBubbles property1={prop1Value} <etc...> />
There are some other issues with the code (at least from the sandbox) that you will need to work out, but this will at least help get you moving in the right direction.

Push dynamically added html list item into last array

How can i push html into the last array. I was trying to add an item and supposed be add instantly into list array. The cod is working except I'm struggling to add new list into last array.
function addItem(id,name){
const array = JSON.parse(localStorage.getItem('categories'));
array.push({
name: name,
id:id,
});
//<li>{name}</li> push this into last array
localStorage.setItem('categories',JSON.stringify(array));
}
{categories.map(function(item, key){
return <div>
<ul>
<li>item.name</li>
</ul>
<button onClick={() => addItem(item.id,'value name')}>Add</button>
</div>
})}
Something looks wrong in your example. I have added a complete exampl. You can maintain localStorage and State both. I hope this example helps you.
You mistake is that while adding new item you are pushing it to localStoage due to which react dom does not get rerendered. You have to update the value of state for that.
class App extends React.Component {
constructor() {
super();
this.state = {
categories: [
{
name: "Hello",
id: 1
},
{
name: "World",
id: 2
}
]
};
this.addItem = this.addItem.bind(this);
this.SaveToLocalStorage = this.SaveToLocalStorage.bind(this);
}
SaveToLocalStorage() {
const categories = this.state.categories;
localStorage.setItem("categories", JSON.stringify(categories));
}
addItem(id, name) {
const categories = this.state.categories;
categories.push({
name: name,
id: id
});
this.setState({ categories });
//localStorage.setItem("categories", JSON.stringify(categories));
}
render() {
let categories = this.state.categories;
const test = categories.map(item => (
<div key={item.id}>
<li>{item.name}</li>
</div>
));
return (
<div>
{test}
<button onClick={() => this.addItem(Date.now(), "Item")}>
Click to Add More
</button>
<button onClick={() => this.SaveToLocalStorage()}>
Save To LocalStorage{" "}
</button>
</div>
);
}
}
ReactDOM.render( < App / > , 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>
I guess this is what you are asking for. You just need to set it to state and re-render it when ever you are trying to add an element to list/array. I don't know why you are setting it to local storage but you can do it from state directly if your intention is to just store the previous array for future additions.
import React, { Component } from "react";
class App extends Component {
state = {};
constructor(props){
super(props);
this.state={
arr = []
}
}
addItem(id, name) {
const array = JSON.parse(localStorage.getItem("categories"));
array.push({
name: name,
id: id
});
//<li>{name}</li> push this into last array
localStorage.setItem("categories", JSON.stringify(array));
this.setState({arr:array});
}
renderList = () => {
return this.state.array.map(function(item, key) {
return (
<div>
<ul>
<li>item.name</li>
</ul>
<button onClick={() => addItem(item.id, "value name")}>Add</button>
</div>
);
});
};
render() {
return <div>{this.renderList()}</div>;
}
}
export default App;

React - iterating over key value pairs in array

I cant get this snippet to output tacos
im not sure what I am doing wrong
let tacos = [{ John: "Guacamole" }, { Sally: "Beef" }, { Greg: "Bean" }];
class Parent extends React.Component {
render() {
return (
<div className="parent-component">
<h3>List of tacos:</h3>
<TacosList tacos={tacos} />
</div>
);
}
}
class TacosList extends React.Component {
render() {
return (
<div className="tacos-list">
{this.props.tacos.map((taco) => {
return
<Parent taco={taco}/>
})}
</div>
);
}
}
render(<Parent />, document.getElementById("root"));
Your problem is that you are breaking into a new line in after return which it's returning undefined while iterating the tacos list.
Furthermore, You will create an infinite loop rendering if you call <Parent /> inside <TacosList />
Either you create a new component to render the items or you do it within the <TacosList /> component
let tacos = [{
person: "John",
ingredient: 'Guacamole'
}, {
person: 'Sally',
ingredient: 'Beef'
}, {
person: 'Greg',
ingredient: 'Bean'
}];
class Parent extends React.Component {
render() {
return (
<div className="parent-component">
<h3>List of tacos:</h3>
<TacosList tacos={tacos} />
</div>
);
}
}
class TacosList extends React.Component {
render() {
return (
<div className="tacos-list">
{this.props.tacos.map((taco, index) => (
<p key={index}>{taco.person}: {taco.ingredient}</p>
))}
</div>
);
}
}
ReactDOM.render(<Parent />, 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>
The problem is
<Parent taco={taco}/>
First parent is not expecting a taco property.
Second I think you intend to actually render the elements to display the taco information there, not a Parent component for each taco.
Start up with creating an atomic component (div, span or IMG) to show the tacos list, in TacosList.
The map in TacosList will work only at the first level, because every item is a JavaScript object, which means you have to know the key, to have the value, or use Object.keys and Object.items to show names.

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.

Use map to create HTML ReactJS

I have an array of objects.
notifications = [
{notification:"this is notification1"},
{notification:"this is notification2"},
{notification:"this is notification3"},
]
Ive been trying to map through the array and create HTML code out of it.
return (
<div>
{notifications.map(function(notificationItem) {
<a> {notificationItem.notification} </a>
})}
</div>
);
Can somebody please tell me what is the mistake in this?
Thank you!
From .map you should return value - add return statement to .map., also in this case you should add key property for each element., because child elements should have unique keys., you can read more about reconciliation here
var App = React.createClass({
render: function() {
const notifications = this.props.notifications
.map(function(notificationItem, index) {
return <a key={index}> {notificationItem.notification} </a>;
});
return <div>{ notifications }</div>;
}
});
var notifications = [
{notification:"this is notification1"},
{notification:"this is notification2"},
{notification:"this is notification3"},
];
ReactDOM.render(
<App notifications={ notifications } />,
document.getElementById('container')
);
<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="container"></div>
I'd also add that if you don't need stateful React, you could also write your component in this style:
const notifications = [
{ notification: "1" },
{ notification: "2" },
{ notification: "3" },
];
const App = function({ notifications }) {
return (
<div>
{
notifications.map((item, index) => <a key={index}>{item.notification}</a>)
}
</div>
)
}
ReactDOM.render(
<App notifications={ notifications } />,
document.getElementById("app")
)

Categories

Resources