Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactjs: Using same form for add and update

Tags:

reactjs

redux

I crafted a reactjs crud app with help of a tutorial and it works great now. Now i am trying to merge two form together so that same form should be used for both add and update operation.

This is my allpost.js file

import React, { Component } from 'react';

import { connect } from 'react-redux';

import Post from '../components/Post';

import EditComponent from '../components/editComponent';

class AllPost extends Component {
    render() {
        return (
            <div>
                <h1>All Posts</h1>
                {this.props.posts.map((post) => (
                    <div key={post.id}>
                        {post.editing ? <EditComponent post={post} key={post.id} /> :
                            <Post key={post.id} post={post} />}
                    </div>
                ))}
            </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        posts: state
    }
}
export default connect(mapStateToProps)(AllPost);

and this is my postForm.js file:

import React, { Component } from 'react';
import { connect } from 'react-redux'


class PostForm extends Component {
  handleSubmit = (e) => {
    e.preventDefault();
    const title = this.getTitle.value;
    const message =  this.getMessage.value;
    const data = {
      id: new Date(),
      title,
      message,
      editing: false
    }
    console.log(data)
    this.props.dispatch({
        type: 'ADD_POST',
        data,
    });
    this.getTitle.value = '';
    this.getMessage.value = '';
  }
render() {
return (
<div>
  <h1>Create Post</h1>
  <form onSubmit={this.handleSubmit}>
   <input required type="text" ref={(input)=>this.getTitle = input} 
    placeholder="Enter Post Title"/>
   <br /><br />
   <textarea required rows="5" ref={(input)=>this.getMessage = input} cols="28" 
    placeholder="Enter Post" />
   <br /><br />
   <button>Post</button>
  </form>
</div>
);
}
}
export default connect()(PostForm);

and this is my editComponent.js file

import React, { Component } from 'react';
import { connect } from 'react-redux';


class EditComponent extends Component {
handleEdit = (e) => {
  e.preventDefault();
  const newTitle = this.getTitle.value;
  const newMessage = this.getMessage.value;
  const data = {
    newTitle,
    newMessage
  }
  this.props.dispatch({ type: 'UPDATE', id: this.props.post.id, data: data })
}
render() {
return (
<div>
  <form onSubmit={this.handleEdit}>
    <input required type="text" ref={(input) => this.getTitle = input}
    defaultValue={this.props.post.title} placeholder="Enter Post Title" /><br /><br />
    <textarea required rows="5" ref={(input) => this.getMessage = input}
    defaultValue={this.props.post.message} cols="28" placeholder="Enter Post" /><br /><br />
    <button>Update</button>
  </form>
</div>
);
}
}
export default connect()(EditComponent);

and this is my post.js file:

import React, { Component } from 'react';
import { connect } from 'react-redux'

class Post extends Component {
  render() {
  return (
    <div>
      <h2>{this.props.post.title}</h2>
      <p>{this.props.post.message}</p>
      <button onClick={() => this.props.dispatch({type: 'EDIT_POST', id: this.props.post.id})}>EDIT
      </button>
      <button onClick={ () => this.props.dispatch({type: 'DELETE_POST', id: this.props.post.id}) }>DELETE
      </button>
    </div>
  );
 }
}
export default connect()(Post);

and this is my postReducer.js file:

const postReducer = (state = [], action) => {
    switch(action.type) {
      case 'ADD_POST':
        return state.concat([action.data]);
      case 'DELETE_POST':
        return state.filter((post)=>post.id !== action.id);
      case 'EDIT_POST':
        return state.map((post)=>post.id === action.id ? {...post,editing:!post.editing}:post)
      case 'UPDATE':
        return state.map((post)=>{
          if(post.id === action.id) {
            return {
               ...post,
               title:action.data.newTitle,
               message:action.data.newMessage,
               editing: !post.editing
            }
          } else return post;
        })
      default:
        return state;
    }
  }
  export default postReducer;

Can anyone please help me to achieve this? I tried a lot to use same form form for both add and update and i failed to achieve this.

like image 747
dudd Avatar asked Aug 14 '19 05:08

dudd


1 Answers

I think it's better you create separate component for rendering form data(FormComponent) and separate components for edit(EditComponent) and add(AddComponent).

This way there will not be clutter in one component and no if/else conditions for different modes like edit or add, or in future copy mode.

This approach will add flexibility and enhances compositional pattern of react.

1) AddComponent

import React, { Component } from 'react';
import { connect } from 'react-redux'


class AddComponent extends Component {
  handleSubmit = (title, message) => {
    const data = {
      id: new Date(),
      title,
      message,
      editing: false
    }
    this.props.dispatch({
        type: 'ADD_POST',
        data,
    });
  }
    render() {
        return (
            <div>
                <h1>Create Post</h1>
                <FormComponent
                    buttonLabel='Post'
                    handleSubmit={this.handleSubmit}
                />
            </div>
        );
    }
}
export default connect()(AddComponent);

2) EditComponent

import React, { Component } from 'react';
import { connect } from 'react-redux';


class EditComponent extends Component {
    handleSubmit = (newTitle, newMessage) => {
        const data = {
            newTitle,
            newMessage
        }
        this.props.dispatch({ type: 'UPDATE', id: this.props.post.id, data: data })
    }

    render() {
        return (
        <div>
            <FormComponent
                buttonLabel='Update'
                handleSubmit={this.handleSubmit}
            />
        </div>
        );
    }
}
export default connect()(EditComponent);

3) FormComponent

import React, { Component } from 'react';

class FormComponent extends Component {
    handleSubmit = (e) => {
        e.preventDefault();
        const title = this.getTitle.value;
        const message =  this.getMessage.value;
        this.props.handleSubmit(title, message);
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <input required type="text" ref={(input) => this.getTitle = input}
                defaultValue={this.props.post.title} placeholder="Enter Post Title" /><br /><br />
                <textarea required rows="5" ref={(input) => this.getMessage = input}
                defaultValue={this.props.post.message} cols="28" placeholder="Enter Post" /><br /><br />
                <button>{this.props.buttonLabel}</button>
            </form>
        );
    }
}
export default FormComponent;

Hope that helps!!!

like image 140
tarzen chugh Avatar answered Nov 04 '22 09:11

tarzen chugh