I have the following array:
const elements = [
{
title: "foo"
section: <div>Foo <button onClick={sayHello}>Greet</button></div>
},
{
title: "bar"
section: <div>Bar <button onClick={sayHello}>Greet</button></div>
}
];
I want to render the component with something like:
const someSections = this.state.elements.map((item, i) => (
<div key={i}>
{item.section}
</div>
));
...
render(){
return (
...
<div>
{someSections}
</div>
)
}
But I can't render them. The error is:
Uncaught Error: objects are not valid as a React child
Check the working solution:
const data = [
{
title: "foo",
section: <div>Foo <button>Greet</button></div>
},
{
title: "bar",
section: <div>Bar <button>Greet</button></div>
}
]
class App extends React.Component{
render(){
return(
<div>
{
data.map((item,i)=>{
return <div key={i}>{item.section}</div>
})
}
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('app')
);
<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='app'></div>
normally you would do something like this.
render(){
let someSections = this.state.elements.map((item, i) => (
<div key={i}>
{item.section}
</div>
));
return (
<div>
{someSections}
</div>
)
}
Related
I'm trying to pass the 'Username' component directly into the 'Comment' component, like I did with the 'ProfilePicture' component, but only the '#' symbol shows up and not the username. Please help, also thanks in advance!
//component
const ProfilePicture = (props) => {
return (
<div>
<img
className="ProfilePicture"
src={props.user.pfpUrl}
alt={props.user.name}
height={50}
width={50}
/>
</div>
)
};
// username component
const Username = (props) => {
return (
<div>
<p>#{props.user.username}</p>
</div>
)
};
// user's comment
const comment = {
username: "guest",
image: {
name: "Default Profile Image",
pfpUrl: 'https://static.vecteezy.com/system/resources/thumbnails/009/292/244/small/default-avatar-icon-of-social-media-user-vector.jpg'
}
}
const Comment = (props) => {
return (
<div>
<ProfilePicture user={props.image} />
<Username user={props.username} />
</div>
)
}
ReactDOM.render(
<Comment image={comment.image} username={comment.username} />,
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">
<!-- This element's contents will be replaced with your component. -->
</div>
You need to access it like props.user in your Username component
//component
const ProfilePicture = (props) => {
return (
<div>
<img
className="ProfilePicture"
src={props.user.pfpUrl}
alt={props.user.name}
height={50}
width={50}
/>
</div>
)
};
// username component
const Username = (props) => {
return (
<div>
<p>#{props.user}</p> // YOU are passing user as a prop to username component
</div>
)
};
// user's comment
const comment = {
username: "guest",
image: {
name: "Default Profile Image",
pfpUrl: 'https://static.vecteezy.com/system/resources/thumbnails/009/292/244/small/default-avatar-icon-of-social-media-user-vector.jpg'
}
}
const Comment = (props) => {
return (
<div>
<ProfilePicture user={props.image} />
<Username user={props.username} />
</div>
)
}
ReactDOM.render(
<Comment image={comment.image} username={comment.username} />,
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">
<!-- This element's contents will be replaced with your component. -->
</div>
Change the <Username> in your Comment component to read:
<Username user={{username:props.username}} />
This matches the way you are retrieving the username later.
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>
);
}
The code was working before I made it into a function so I am trying to figure out what is the difference and how to fix it.
import React from 'react';
const Ninjas = ({list}) => {
const ninjaList = list.map( ninjan => {
return (
<div className="ninja" key={ninjaList.id}>
<div>Name : {ninjan.name}</div>
<div>Age: {ninjan.age}</div>
<div>Belt:{ninjan.belt}</div>
</div>
)
})
return(
<div className="ninja-list">
{ninjaList}
</div>
)
}
export default Ninjas
you should try it like this:
import React from 'react';
const Ninjas = ({list}) => {
const ninjaList = list.map( (ninjan , index)=> {
return (
<div className="ninja" key={index}>
<div>Name : {ninjan.name}</div>
<div>Age: {ninjan.age}</div>
<div>Belt:{ninjan.belt}</div>
</div>
)
})
return(
<div className="ninja-list">
{()=>ninjaList()}
</div>
)
}
export default Ninjas
You probably have a typo in this line:
<div className="ninja" key={ninjaList.id}>
You are referencing to the list not to the list element.
This is sample code.
const ninjan = [ { id: 1, name: 'adasdasdasd' },{ id: 2, name: '123' }] ;
const ninjaList = ninjan.map( (ninjan)=> {
return (
<div className="ninja" key={ninjan.id}>
<div>Name : {ninjan.name}</div>
<div>Id : {ninjan.id}</div>
</div>
)
})
return (
<div className="content">
{ Object.keys(ninjaList).length >0 &&
ninjaList
}
</div>
);
I am making a card that lists radio stations and when you click on a station a picture drops down for that list item. all data i am pulling from a json.
I have tried building the list in the toggle.js and in the app.js files
app.js-- div with toggle (its all inside a card..many divs)
<div class="card-trip-infos">
<div>
<Toggle />
</div>
<img class="card-trip-user avatar-bordered"/>
</div>
toggle.js render block:
state = {
on: false,
}
toggle = () => {
this.setState({
on: !this.state.on
})
}
render() {
return (
<ul>
<div>
<p>{PostData.radios[0].name}</p>
{PostData.radios.map((postDetail, index) => {
return <div>
<li onClick={this.toggle}>
<span id='radioName'>{postDetail.name}</span> <span id='frequency'>{postDetail.frequency}</span>
</li>
{
this.state.on && <img src='imagesrc'></img>
}
</div>
})}
</div>
</ul>
)
}
}
I dont know what exactly is wrong but i expect to be able to toggle a picture for each list row seperately. i am confused where to iterate over my json and where to plug everything in.
many Thanks!!
Since we don't know your toggle function and all your component we can't make exact suggestions but in order to do what you want here (just toggle the selected item), you have two different approaches.
You can keep the selected state in the component itself.
class App extends React.Component {
state = {
cards: [
{ id: 1, name: "foo" },
{ id: 2, name: "bar" },
{ id: 3, name: "baz" }
],
};
render() {
const { cards } = this.state;
return (
<div>
{cards.map(card => (
<Card
key={card.id}
card={card}
/>
))}
</div>
);
}
}
class Card extends React.Component {
state = {
selected: false
};
handleSelect = () =>
this.setState(state => ({
selected: !state.selected
}));
render() {
const { card } = this.props;
return (
<div
className={this.state.selected ? "selected" : ""}
onClick={this.handleSelect}
>
{card.id}-{card.name}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
.selected {
background-color: red;
}
<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" />
You can keep the selected state in the parent component.
class App extends React.Component {
state = {
cards: [
{ id: 1, name: "foo" },
{ id: 2, name: "bar" },
{ id: 3, name: "baz" }
],
selected: {}
};
handleSelect = id =>
this.setState(state => ({
selected: { ...state.selected, [id]: !state.selected[id] }
}));
render() {
const { cards, selected } = this.state;
return (
<div>
{cards.map(card => (
<Card
key={card.id}
card={card}
handleSelect={this.handleSelect}
selected={selected[card.id]}
/>
))}
</div>
);
}
}
const Card = ({ card, handleSelect, selected }) => {
const handleClick = () => handleSelect(card.id);
return (
<div className={selected ? "selected" : ""} onClick={handleClick}>
{card.id}-{card.name}
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
.selected {
background-color: red;
}
<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" />
Create a component for individual list item, have a state there which will hold a boolean property to tell whether the image is to be shown or not. Render function will look something like this:
render (
return (
<li onClick="this.toggleShowImage()">
<div> {props.data.name} </div>
<div> {props.data.frequency} </div>
{this.state.showImage ? <img src='imageUrl' /> : null }
</li>
)
)
Then in toggle.js iterate through your data and create the list components. The render function will look something like below:
render() {
return (
<ul>
{PostData.radios.map((postDetail, index) => {
return <ListItem key={postDetail.name} data={postDetail} />
})}
</ul>
)
}
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')
);