Reputation: 45
So I have two components... and I want them to render one after the other... THe code is below
var Recipe = React.createClass({
getInitialState: function(){
return {editing:false},
{titles: []}
},
edit: function (){
this.setState({editing:true});
},
remove: function(){
this.props.deleteFromBoard(this.props.index)
},
save: function (){
this.props.updateRecipeText(this.refs.newText.value,this.props.index)
this.setState({editing:false});
},
renderNormal: function() {
return (
<div className="recipeContainer">
<div>{this.props.children}</div>
<button onClick ={this.edit} className ="button-primary">Edit</button>
<button onClick ={this.remove} className ="button-remove">Remove</button>
</div>
);
},
renderForm: function() {
return (
<div className="recipeContainer">
<textArea ref="newText" defaultValue ={this.props.children}></textArea>
<button onClick ={this.save} className ="button-danger">Save</button>
</div>
);
},
render: function() {
if(this.state.editing){
return this.renderForm();
}
else{
return this.renderNormal();
}
}
});
var RecipeTitle = React.createClass({
getInitialState: function(){
return {editingTitle:false}
},
edit: function (){
this.setState({editingTitle:true});
},
remove: function(){
this.props.deleteFromBoard(this.props.index)
},
save: function (){
this.props.updateTitle(this.refs.newTextTitle.value,this.props.index)
this.setState({editingTitle:false});
},
renderTitleNormal: function(){
return(
<div>
<h2>{this.props.children}</h2>
<button onClick = {this.edit}>Edit</button>
</div>
)
},
renderTitleForm: function() {
return (
<div>
<textArea ref="newTextTitle" ></textArea>
<button onClick ={this.save} className ="button-danger">Save</button>
</div>
);
},
render: function() {
if(this.state.editingTitle){
return this.renderTitleForm();
} else{
return this.renderTitleNormal();
}
}
});
var Board = React.createClass({
getInitialState: function () {
return {
recipes: [
],
titles: [
]
}
},
add: function(text,title){
var arr = this.state.recipes;
arr.push(text);
this.setState({recipes: arr})
var arrTitle = this.state.titles;
arrTitle.push("Title");
this.setState({titles: arrTitle})
},
removeRecipe: function (i) {
var arr = this.state.recipes;
console.log(arr);
arr.splice(i,1);
this.setState({recipes: arr})
},
removeTitle: function (i) {
var arr = this.state.titles;
arr.splice(i,1);
this.setState({titles: arr})
},
updateRecipe: function (newText, i) {
var arr = this.state.recipes;
arr[i]=newText;
this.setState({recipes: arr})
},
eachTitle: function (title, i){
return (<div><RecipeTitle key={i} index={i} updateTitleText={this.updateTitle} >{title}</RecipeTitle></div>);
},
updateTitleText: function (newTitle, i) {
var arr = this.state.titles;
arr[i]=newTitle;
this.setState({titles: arr})
},
eachRecipe:
function (text, i){
return (<div><Recipe key={i} index={i} updateRecipeText={this.updateRecipe} deleteFromBoard={this.removeRecipe}>{text}</Recipe></div>);
},
eachTitle:
function (title, i){
return (<div><RecipeTitle key={i} index={i} updateTitle ={this.updateTitleText} deleteFromBoard={this.removeRecipe}>{title}</RecipeTitle></div>);
},
render: function () {
return(
<div>
<button onClick={this.add.bind(null,'Default Text')}>Add New</button>
<div >
{this.state.titles.map(this.eachTitle)}
{this.state.recipes.map(this.eachRecipe)}
</div>
</div>
);
}
});
ReactDOM.render(<Board />
, document.getElementById("app"));
Basically its a recipe title followed by a recipe. The problem is once I render a few what happens is that all the titles go together and not with each recipe eg... I want it like this..
Chicken Reicpe
Recipe here
Beef Recipe
Recipe Here
Cococnut Recipe
Recipe here
Instead its like this.
Chicken Recipe
Beef Recipe
Coconut Recipe
Recipe
Recipe
Recipe
How can I render them together? If you need more code or clarification let me know. Any suggestions to improve code? If it's too long to read let me know too. Thanks,
Upvotes: 1
Views: 476
Reputation: 11
I don't know what your data look like. So I suppose the two states data will look like this
repTitles: [{
text: 'chicken'
}, {
text: 'beef'
}],
repFormulars: [{
text: 'chicken-rep'
}, {
text: 'beef-rep'
}]
Then in your render function, you can simply loop through it like
render: function() {
return (
<div>
{this.state.repTitles.map((title, idx) => {
return (
<div>
<p>{title.text}</p>
<p>{this.state.repFormulars[idx].text}</p>
</div>
);
})}
</div>
);
}
It's straightforward so you can get the idea easily. You could add className to the <p>
tag, in case you want to customize it using stylesheet.
Upvotes: 1
Reputation: 282110
You can just access the recipes from recipe array by the index, when iterating through the recipe array
render(){
var recipe = [...this.state.recipe];
return(
<div>
{this.state.recipeTiles.map((title, index) => {
return (
<div key={index}>
<div>{title}</div>
<div>{recipe[index]}</div>
</div>
)
});
</div>
)
}
Upvotes: 0
Reputation: 3478
You'll want to associate each recipe with a recipe title and then render them together. Your render method should sort of look like this:
render(){
// This gives us a container that has recipe and title properties
const recipeContainers = this.state.recipes.map( (recipe, index) => {
const title = this.state.recipeTiles[index]
return {
title,
recipe
}
})
// Now that we have the info bundled together, we can spit it out on the page
return (
<div>
{recipeContainers.map( ({recipe, title}) => (
<dl>
<dt>{this.eachTitle(title)}</dt>
<dd>{this.eachRecipe(recipe)}</dt>
</dl>
)
</div>
)
}
Upvotes: 0
Reputation: 112917
Just use a old fashioned loop. Instead of this:
render() {
return (
<div>
{this.state.recipeTiles.map(this.eachTitle)}
{this.state.recipes.map(this.eachRecipe)}
</div>
);
}
You could e.g. do this:
render() {
const result = [];
const { recipeTiles, recipes } = this.state;
for(let i = 0; i < recipeTiles.length; i++) {
result.push(this.eachTitle(recipeTiles[i]));
result.push(this.eachRecipe(recipes[i]));
}
return (
<div>
{result}
</div>
);
}
Upvotes: 0
Reputation: 11207
You will have to reconcile the two lists. Suppose recipeTiles
has a property of recipe_id
and recipe
has a property of id
. You can simply do something like this:
renderRecipes() {
const { recipes, recipeTiles } = this.props;
recipes.map(recipe => {
const tile = recipeTiles.find(({ recipe_id }) => recipe_id === recipe.id);
return (
<div>
<RecipeTile {...tile} />
<Recipe {...recipe} />
</div>
);
}))
}
Upvotes: 0