Reputation: 992
I'm new to React and JSX and have created a component which displays a title and image which will serve all as a link. I would now like to set the title and image by iterating through JSON data (currently my JSON is accessible via a locally defined variable).
I would like to know how to dynamically create and populate the components with the appropriate data. My code currently looks like this:
<script>
var RecipeList = React.createClass({
const items = [
{
id: 2234567,
title: "Fried Chicken",
image-url: "https://images.media-allrecipes.com/userphotos/560x315/4577069.jpg",
ingredient: ["Chicken", "Flour", "Eggs", "Salt", "Pepper"]
},
{
id: 2234567,
title: "Grilled Chicken",
image-url: "https://images.media-allrecipes.com/userphotos/560x315/4577069.jpg",
ingredient: ["Chicken", "Olive oil", "Salt", "Pepper"]
}
]
getDefaultProps: function() {
return {items: []}
},
render: function() {
var listItems = this.props.items.map(function(item) {
return(
<div className="container-fluid">
<div className="row">
<div className="recipeContainer col-sm-12 col-md-6 col-lg-4">
<h3 className="recipeTitle">{this.props.title}</h3>
<div className="recipeImage">
<img src="{this.props.image}" />
</div>
<div className="recipeBtn">See recipe</div>
</div>
</div>
</div>
);
});
return (
{listItems}
);
}
});
ReactDOM.render(
<div>
<IngredientList></IngredientList>
<RecipeList items={items}></RecipeList>
<RecipeSection></RecipeSection>
</div>
, document.getElementById("module"));
</script>
Upvotes: 0
Views: 1196
Reputation: 30370
This can be achieved by passing the JSON data into the items
prop of your <RecipeList />
so that this data is used to dynamically render the component via that data.
Additionally, there are a few other things to update to get this to work:
you'll want to fix the format of your input JSON so that item keys are either wrapped with quotes, or don't have hyphens.
ensure you're accessing data from the item
in map()
when rendering the list items, rather than accessing the item data from this
wrap the list items that you're rendering with a "root element" at the return
line of your render()
method. A simple solution is to usually wrap the return result with a <div>
, however with more recent versions of React you can use <React.Fragment>
(this allows you to return multiple elements in a render()
result, without adding the extra "div element" to be resulting DOM).
Here's a working snippet:
<div id="module"></div>
<script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script>
<script type="text/babel">
/*
Use class to define component using React16
*/
class RecipeList extends React.Component {
render() {
var listItems = this.props.items.map(function(item) {
return(
<div className="container-fluid">
<div className="row">
<div className="recipeContainer col-sm-12 col-md-6 col-lg-4">
<h3 className="recipeTitle">{item.title}</h3> { /* <-- Corrected this to use item.title */ }
<div className="recipeImage">
<img src={item.image} /> { /* <-- Corrected this to use item.image */ }
</div>
<div className="recipeBtn">See recipe</div>
</div>
</div>
</div>
);
});
/*
When rendering multiple DOM elements as a list, you
must wrap these with React.Fragment, or something else
like a div
*/
return (<React.Fragment>{listItems}</React.Fragment>);
}
};
/*
Declare items data array which will passed to the items
prop of the <RecipeList> component
*/
const items = [{
'id': 2234567,
'title': "Fried Chicken",
'image': "https://images.media-allrecipes.com/userphotos/560x315/4577069.jpg",
'ingredient': ['Chicken', 'Olive oil', 'Salt', 'Pepper']
},
{
'id': 2234567,
'title': "Grilled Chicken",
'image': "https://images.media-allrecipes.com/userphotos/560x315/4577069.jpg",
'ingredient': ['Chicken', 'Olive oil', 'Salt', 'Pepper']
}];
ReactDOM.render(
<div>
{ /* Pass the items data array to the items prop */ }
<RecipeList items={items}></RecipeList>
</div>,
document.getElementById("module"));
</script>
Hope that helps!
Upvotes: 1