Use map to create HTML ReactJS - javascript

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

Related

ReactJS: Map array of objects

I am trying to map array of objects [{thing: '', quantity: ''}] with ReactJS and this is the code i use for it (and it does not work).
EDIT this is the original code
<ul>
{this.state.ingredients.map(({i,q},k)=>{
return (
<div key={k}>
<li>{i} - {q}</li><br/>
</div>
)
})}
</ul>
what is the reason?
Pass the properties to your map. When destructuring objects, you need to provide the exact keys.
for example, doing the following returns undefined, since obj doesn't have the given props. Object_destructuring
const obj = {a: 'a', b: 'b'}
const { c, d} = obj;
console.log(c, d);
{this.state.things.map(({ thing, quantity }, k) => {
return (
<div key={k}>
<li key={k}>{thing} - {quantity}</li><br />
</div>
)
})}
DEMO
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component {
constructor() {
super();
this.state = {
name: 'React',
things: [{ thing: 'Thing ', quantity: 23 }],
};
}
render() {
return (
<div>
{this.state.things.map(({ thing, quantity }, k) => {
return (
<div key={k}>
<li key={k}>{thing} - {quantity}</li><br />
</div>
)
})}
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
</script>
Probably you are looking for something like this, you are not destructuring correctly.
const obj = {thing:'something',quantity:1};
const arr = [obj];
{
arr.map(({ thing, quantity }, index) => {
return (
<div key={index}>
<li>{thing} - {quantity}</li><br/>
</div>
)
})}
<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>

How can I grab the key of a list item generated from a map function?

So I am learning React, and I've tried searching for solutions to my problem both on stackoverflow and on React's own documentation, but I am still stumped.
Essentially, I have a list of 10 subreddits that is being mapped to list items in the form of the subredditsArray variable.
I render the results, and try to pass the selected item when I click that list item to my getSubredditInfo function. However, this doesn't work - event.target.key is undefined. (To clarify, I am looking to grab the key of the single list element that I have clicked).
When I try to just get event.target, I get the actual htmlElement (ex: <li>Dota2</li>), where as I want to get the key, or at least this value into a string somehow without the tags. I also tried putting my onClick method in the list tag of the map function, but that did not work.
Here is the relevant code:
//this is where I get my data
componentDidMount(){
fetch('https://www.reddit.com/api/search_reddit_names.json?query=dota2')
.then(results => {
return results.json();
})
.then(redditNames => {
//this is there I set my subreddits state variable to the array of strings
this.setState({subreddits: redditNames.names});
})
}
getSubredditInfo(event){
//console.log(event.target.key); <-- DOESNT WORK
}
render() {
var subredditsArray = this.state.subreddits.map(function(subreddit){
return (<li key={subreddit.toString()}>{subreddit}</li>);
});
return (
<div className="redditResults">
<h1>Top 10 subreddits for that topic</h1>
<ul onClick={this.getSubredditInfo}>{subredditsArray}</ul>
</div>
);
}
My questions essentially boil down to:
How do I grab the key value from my list object?
Additionally, is there a better way to generate the list than I currently am?
Thank you in advance.
EDIT: Added my componentDidMount function in hopes it clarifies things a bit more.
try the following code:
class App extends React.Component {
constructor(props){
super(props);
this.state = {subreddits:[]};
}
componentDidMount(){
fetch('https://www.reddit.com/api/search_reddit_names.json?query=dota2')
.then(results => {
return results.json();
})
.then(redditNames => {
//this is there I set my subreddits state variable to the array of strings
this.setState({subreddits: redditNames.names});
})
}
getSubredditInfo(subreddit){
console.log(subreddit);
}
render() {
return <div className="redditResults">
<h1>Top 10 subreddits for that topic</h1>
<ul>
{
this.state.subreddits.map((subreddit)=>{
return (<li key={subreddit.toString()} onClick={()=>this.getSubredditInfo(subreddit)}>{subreddit}</li>);
})
}
</ul>
</div>;
}
}
ReactDOM.render(
<App/>,
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">
<!-- This element's contents will be replaced with your component. -->
</div>
please check the onClick event handler now. its an arrow function and its calling the getSubredditInfo function with your subreddit now. so you will get it there.
so its basically different way of calling the handler to pass data to the handler.
it works as you expect it to.
You can use lamda function or make component for item list which have own value for getSubredditInfo function
getSubredditInfo(value) {}
render() {
var subredditsArray = this.state
.subreddits.map((subreddit, i) =>
(<li key={i}
onClick={() => this.getSubredditInfo(subreddit)}>{subreddit}</li>));
return (
<div className="redditResults">
<h1>Top 10 subreddits for that topic</h1>
<ul>{subredditsArray}</ul>
</div>
);
}
1) Key should be grabbed either by the id in your object in array. Or you can combine the 2 properties to create a unique key for react to handle re-renders in a better way.
If you have a string array, you may use a combination of string value + index to create a unique value, although using index is not encouraged.
Given a quick example for both below.
2) A better way could be to move your map function into another function and call that function in render function, which will return the required JSX. It will clean your render function.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
subredditsObjArray: [
{ id: 1, value: 'A'},
{ id: 2, value: 'B'},
{ id: 3, value: 'C'},
{ id: 4, value: 'D'}
],
subredditsArray: ['A', 'B', 'C', 'D'],
selectedValue: ''
};
}
getSubredditInfo = (subreddit) => {
console.log(subreddit)
this.setState({
selectedValue: ((subreddit && subreddit.id) ? subreddit.value : subreddit),
});
}
render() {
return (
<div className="redditResults">
<p>Selected Value: {this.state.selectedValue}</p>
<h1>Top {this.state.subredditsArray.length || '0'} subreddits for that topic</h1>
<p>With Objects Array</p>
<ul>
{
this.state.subredditsObjArray
&& this.state.subredditsObjArray.map(redditObj => {
return (<li key={redditObj.id}><button onClick={() => this.getSubredditInfo(redditObj)}>{redditObj.value || 'Not Found'}</button></li>);
})
}
</ul>
<br />
<p>With Strings Array</p>
<ul>
{
this.state.subredditsArray
&& this.state.subredditsArray.map((reddit, index) => {
return (<li key={reddit + '-' + index}><button onClick={() => this.getSubredditInfo(reddit)}>{reddit || 'Not Found'}</button></li>);
})
}
</ul>
</div>
);
}
}
ReactDOM.render(
<App etext="Edit" stext="Save" />,
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">
<!-- This element's contents will be replaced with your component. -->
</div>
Are you trying to do this? I'm not sure what you want to do.
getSubredditInfo(e, subreddit) {
console.log(subreddit)
}
render() {
const { subreddits } = this.state
var subredditsArray = subreddits.map(subreddit => (
<li
key={subreddit.toString()}
onClick={(e) => {
this.getSubredditInfo(e, subreddit)
}}
>
{subreddit}
</li>
))
return (
<div className="redditResults">
<h1>Top 10 subreddits for that topic</h1>
<ul>{subredditsArray}</ul>
</div>
);
}
The key purpose is to pass your subreddit to the onClick function so you will receive the value while you click the item.
If you still get error try this and tell me what's happened.
render() {
const { subreddits } = this.state
var subredditsArray = subreddits.map(subreddit => (
<li
key={subreddit.toString()}
onClick={(e) => {
console.log(subreddit.toString())
}}
>
{subreddit}
</li>
))
return (
<div className="redditResults">
<h1>Top 10 subreddits for that topic</h1>
<ul>{subredditsArray}</ul>
</div>
);
}

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.

how to parse loop for json in react js

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.

map images concatenating strings

I am using the map function to iterate over an array with images. I am then trying to display these images on the page.
You will see that the images are being concatenated into one stain. Does anyone know how to do this so i can show each individual image?
I have set up a jsfiddle here
Please see React code below:
var App = React.createClass({
render: function(){
var images = [
{
id:"1",
images:['https://i.scdn.co/image/dc284fcd7e581aa2b7ca56f28c7c74f0ca0ad393', 'https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7']
},
{
id:"2",
images:['https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7', 'https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7']
}
];
return(<List images={images} />)
}
});
var List = React.createClass({
render: function() {
var images = this.props.images.map(function(image){
return(image.images[0]); // updated here
})
return(
<div>
<img src={images}></img>
<p>{images}</p>
</div>
)
}
});
ReactDOM.render(
<App name="World" />,
document.getElementById('container')
);
Does the following work? https://jsfiddle.net/petebere/19fmn5qs/
The change was to add the <img /> tag with the src attribute set to the url:
var images = this.props.images.map(function(image, index){
return <img key={index} src={(image.images[0])} />;
});
Also, you now don't need the <img /> tag in your final return statement. Please see my updated fiddle. I've also added the key attribute as required in the React docs: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children
Full code:
var App = React.createClass({
render: function() {
var images = [
{
id:"1",
images:['https://i.scdn.co/image/dc284fcd7e581aa2b7ca56f28c7c74f0ca0ad393', 'https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7']
},
{
id:"2",
images:['https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7', 'https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7']
}
];
return(<List images={images} />);
}
});
var List = React.createClass({
render: function() {
var images = this.props.images.map(function(image, index){
return <img key={index} src={(image.images[0])} />;
});
return(
<div>
<p>Your images</p>
{images}
</div>
);
}
});
ReactDOM.render(
<App name="World" />,
document.getElementById('container')
);

Categories

Resources