React.js:使用相同的表单进行添加和更新

时间:2019-08-14 05:44:36

标签: reactjs redux

我在一个教程的帮助下制作了一个reactjs crud应用程序,它现在运行良好。现在,我正在尝试将两种形式合并在一起,以便对addupdate操作都应使用同一形式。

这是我的allpost.js文件

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

这是我的postForm.js文件:

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

这是我的editComponent.js文件

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

这是我的post.js文件:

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

这是我的postReducer.js文件:

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;

有人可以帮助我实现这一目标吗?我为添加和更新尝试了很多尝试使用相同的表单表单,但未能实现。

2 个答案:

答案 0 :(得分:2)

您可以使用editMode属性创建自己的Form组件,以控制它是Create还是Update。

import React, {Component} from 'react';
import PropTypes from 'prop-types';

class Form extends Component {
    handleSubmit = e => {
        e.preventDefault();
        const {editMode, post} = this.props;
        const title = this.titleRef.value;
        const body = this.bodyRef.value;
        if (editMode){
            const data = {
                title,
                body
            }
            this.props.dispatch({type: 'UPDATE', id: post.id, data})
        }
        else {
            const data = {
                id: new Date(),
                title,
                message,
                editing: false
            }
            this.props.dispatch({type: 'ADD_POST', data});
        }
    }

    render() {
        const {editMode, post} = this.props;
        const pageTitle = editMode ? 'Edit Post' : 'Create Post';
        const buttonTitle = editMode ? 'Update' : 'Post';
        return (
            <div>
                <h1>{pageTitle}</h1>
                <form onSubmit={this.handleSubmit}>
                    <input
                        required
                        type="text"
                        ref={input => this.titleRef = input}
                        placeholder="Enter Post Title"
                        defaultValue={post.title}
                    />
                    <textarea
                        required
                        rows="5"
                        ref={input => this.bodyRef = input}
                        cols="28"
                        placeholder="Enter Post"
                        defaultValue={post.body}
                    />
                    <button>{buttonTitle}</button>
                </form>
            </div>
        );
    }
}

Form.propTypes = {
    editMode: PropTypes.bool,
    post: PropTypes.object
}

Form.defaultProps = {
    editMode: false,    // false: Create mode, true: Edit mode
    post: {
        title: "",
        body: ""
    }    // Pass defined Post object in create mode in order not to get undefined objects in 'defaultValue's of inputs.
}

export default Form;

默认情况下它将处于创建模式,但是如果您要更新帖子,则应将editMode={true}传递给表单组件。

答案 1 :(得分:2)

我认为最好创建单独的组件来呈现表单数据(FormComponent),并创建单独的组件进行edit(EditComponent)和add(AddComponent)。

这样,就不会在一个组件中造成混乱,并且对于editadd等不同模式,或将来的copy模式,也不会出现if / else条件。

这种方法将增加灵活性并增强组成反应模式。

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;

希望有帮助!