Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React component with Edit Mode and View Mode, is this a correct pattern?

I have a react component which displays a recipe. This component can be used to just view the data and also to edit the data, depending on a 'edit' prop being passed it.

At the moment I have some conditional logic which will hide/show certain elements depending on whether the user wants to edit or view the recipe. Here is my render function:

render() {
    let buttons = null;
    if (this.props.edit === 'true') {
        buttons = <div className="buttonList">
            <button onClick={this.onSave} className='defaultBtn'>Save</button>
            <button onClick={this.goBack} className='defaultBtn'>Discard Changes</button>
        </div>;
    } else {
        buttons = <div className="buttonList">
            <button onClick={this.goBack} className='defaultBtn'>Back</button>
        </div>;
    }
    return (
        <div className="single">
            <img src={this.state.recipe.imageURL} />
            <div className='recipeDetails'>
                <h1>{this.state.recipe.name}</h1>
                {this.props.edit === 'true' > 0 &&
                    <TextField type='text' floatingLabelText='Image URL' onChange={this.onImageUrlChange}></TextField>
                }
                <IngredientList onIngredientChange={this.onIngredientChange}
                    onDelete={this.onDelete}
                    ingredients={this.state.recipe.ingredients}
                    edit={this.props.edit}
                    addIngredient={this.addIngredient} />
                {buttons}
            </div>
        </div>
    );
}

Is this the best way to achieve this? Using if statements like this feels wrong to me. I feel like I should have a ViewRecipe component and a EditRecipe component that share most of the code but have some logic to hide and show the relevant elements. Is there a certain React Pattern to do this? I've read a little about High Order Components but not sure if they fit this particular problem.

Am I overcomplicating this? Should I just have two separate components? Most of the logic on the Edit side of things.

like image 430
Thomas Collins Avatar asked Feb 07 '17 01:02

Thomas Collins


People also ask

Is React MVVM or MVC?

React isn't an MVC framework. React is a library for building composable user interfaces. It encourages the creation of reusable UI components which present data that changes over time.

What pattern is React in architecture?

React is fundamentally different from several other user interface libraries and web frameworks; it does not have a fixed architectural pattern. Instead, it is fully customizable based on the purpose of the UI, and as a component-oriented approach, it is suitable for the gradual improvement of React applications.

Does React follow MVC pattern?

React isn't an MVC framework. React is a library for building composable user interfaces. While this is true, the term MVC framework is more of a marketing term. The original MVC concept is closer to a design pattern and has nothing to do with frameworks.


1 Answers

  1. Your props naming needs review :

    props.edit ='true' 🤔 it can be props.mode = 'edit' or 'view'

  2. mitigate the conditional logic (if...else) of render method and break down it into methods prefixed by "render".

  3. Solution will be :

      renderButtons() {
        if (this.props.mode === 'edit') 
          return (
            <div className="buttonList">
                <button onClick={this.onSave} className='defaultBtn'>Save</button>
                <button onClick={this.goBack} className='defaultBtn'>Discard Changes</button>
            </div>
          )
        else {
          return (
             <div className="buttonList">
                <button onClick={this.goBack} className='defaultBtn'>Back</button>
              </div>
           ) 
        }
      }
    
      renderTextField() {
        if (this.props.mode != 'edit') return null;
        return (
          <TextField type='text' floatingLabelText='Image URL' onChange={this.onImageUrlChange}></TextField>
        )
      }
    
    
    
      render() {
    
          return (
              <div className="single">
                  <img src={this.state.recipe.imageURL} />
                  <div className='recipeDetails'>
                      <h1>{this.state.recipe.name}</h1>
                      {this.renderTextField()}
                      <IngredientList onIngredientChange={this.onIngredientChange}
                          onDelete={this.onDelete}
                          ingredients={this.state.recipe.ingredients}
                          edit={this.props.edit}
                          addIngredient={this.addIngredient} />
                      {this.renderButtons()}
                  </div>
              </div>
          );
      }
    
like image 166
Abdennour TOUMI Avatar answered Oct 02 '22 06:10

Abdennour TOUMI