1

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,

4
  • you want to render the same recipes for all recipeTiles ? can you show the array and more code of those two functions ? Commented May 19, 2017 at 13:04
  • Why do you have your data separated anyway? It would be much cleaner to keep the titles with the recipes, since a title is part of the overall recipe. Instead of mucking around with your dual-array structure, fix your data, and have a <Recipe /> component that renders the title and recipe. Commented May 19, 2017 at 13:58
  • Thanks Dave. I will try that later Commented May 22, 2017 at 12:24
  • How can you add then a recipe and title to the one array as a state? Is that possible? Commented May 22, 2017 at 12:25

5 Answers 5

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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>
    );
  }))
}

Comments

0

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>
  );
}

Comments

0

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

}

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.