我想从一个组件上的表单收集一些数据,并在另一个组件上显示它

时间:2018-09-23 17:10:31

标签: reactjs react-redux react-router

我正在尝试收集有关组件的一些详细信息,并在短2页的另一个组件中显示它。但是我不知道这是怎么回事,它会收集数据,但不会在下一个组件redux存储,动作减少器上显示所有创建的东西。有人可以告诉我我做错了什么或我想念什么吗? 谢谢

GetDetail.js

import React, {Component} from 'react';
import {connect} from 'react-redux';
import * as Actions from '../Actions/Action'

class GetDetails extends Component{
    constructor(props, context){
        super(props, context);
        this.state={
            details:{
                name:"",
                price:"",
                company:"",
                manufacture:"",
                expiry:""
             }

         };
        this.HandleSubmit = this.HandleSubmit.bind(this);

     }
     HandleSubmit() {
        this.props.SubmitDetails(this.state.details);
     }

    render(){
        return(
            <div className="container" >
            <form>
            <h1>Enter Details Here</h1>
            <div className="form-group">
                    <label>Name</label>
                    <input type="text" className="form-control" id="inputEmail4" placeholder="Email"
                           onChange={(e)=> this.setState({details: Object.assign(this.state.details, {name: e.target.value})})}
                           value={this.state.text}/>
            </div>
            <div className="form-group">
                <label >Price</label>
                <input type="text" className="form-control" id="inputAddress" placeholder="1234 Main St"
                       onChange={(e)=> this.setState({details: Object.assign(this.state.details, {price: e.target.value})})}
                       value={this.state.text}/>
            </div>
            <div className="form-group">
                <label >Company</label>
                <input type="text" className="form-control" id="inputAddress2"
                       placeholder="Apartment, studio, or floor"
                       onChange={(e)=> this.setState({details: Object.assign(this.state.details, {company: e.target.value})})}
                       value={this.state.text}/>
            </div>
            <div className="form-group">
                <label >Type</label>
                <select id="inputState" className="form-control">
                    <option selected>Choose...</option>
                    <option>New</option>
                    <option>Used</option>
                </select>
            </div>
                <div className="form-group ">
                    <label >Expiry Date</label>
                    <input type="text" className="form-control" id="inputCity"
                           onChange={(e)=> this.setState({details: Object.assign(this.state.details, {manufacture: e.target.value})})}
                           value={this.state.text}/>
                </div>
                <div className="form-group ">
                    <label>Manufacture Date</label>
                    <input type="text" className="form-control" id="inputZip"
                           onChange={(e)=> this.setState({details: Object.assign(this.state.details, {expiry: e.target.value})})}
                           value={this.state.text}/>
                </div>

            <button type="submit" className="btn btn-primary" value="Save"  onClick={this.HandleSubmit}>Submit</button>
        </form>
        </div>

    );
}
}


function mapDispatchToProps(dispatch) {
    return {
        SubmitDetails: details => dispatch(Actions.SubmitDetails(details))
    }
}

export default connect(mapDispatchToProps) (GetDetails);

ShowDetails.js

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

class ShowDetails extends Component{
     diplayDetails(details, index){
        return (
         <tr key={index}>
               <td>{details.name}</td>
               <td>{details.price}</td>
               <td>{details.company}</td>
               <td>{details.price}</td>
               <td>{details.expiry}</td>
                <td>{details.manufacture}</td>
           </tr>
         )

}
render(){
    return(
        <div className="container2">
            <h1> Show Details </h1>

            <table className="table">
                <thead className="thead-light">
                <tr>
                    <th scope="col">Name</th>
                    <th scope="col">Price</th>
                    <th scope="col">Company</th>
                    <th scope="col">Type</th>
                    <th scope="col">Expiry</th>
                    <th scope="col">Handle</th>

                </tr>
                </thead>
                <tbody>
                {this.props.detail.map(this.diplayDetails)}
                </tbody>
            </table>
        </div>
    );
}
}





 function mapStateToProps(state) {
    return{
        detail: state.detail
     };

 }

 export default connect (mapStateToProps) (ShowDetails);

Reducers.js

export default function productReducer(state=[], action) {
    switch (action.type) {
        case 'ADD_PRODUCT':
            return[...state,
                Object.assign({}, action.details)

            ];
        default:
            return state;
     }
 }

针对rootreducers的index.js

 import {combineReducers} from 'redux';
 import ProductReducer from './Reducers';

 const rootReducer = combineReducers({
     detail: ProductReducer
 });

 export default root

Actions.js

 export function SubmitDetails(details) {
     return{ type: 'ADD_PRODUCT',details }

  }

1 个答案:

答案 0 :(得分:2)

好的,有很多调整,但总结一下:

  • 所有this.setState()调用都应使用类方法进行。
  • connect()需要2个参数:mapStateToPropsmapDispatchToProps ...如果不使用mapStateToProps,则必须传入null作为第一个参数。 / li>
  • 您的表单输入名称到处都是。保持一致:<input name="name" value={this.state.name} onChange={this.handleChange} />。既不需要也不建议使用输入id。在这种情况下,this.handleChange利用e.target.namee.target.value来跟踪输入及其值。
  • 在允许用户提交之前,请确保所有输入均已填写。
  • 避免在render方法中使用粗箭头功能,例如:onChange={ (e) => this.handleChange(e) },因为它们将在每次重新渲染组件时被复制。有时它们是不可避免的,但目的是最大程度地减少使用。
  • 检查边缘情况(例如details为空),否则,尝试map未定义或为空的对象时,您的应用将崩溃。
  • 动作应返回payload(标准命名约定)。

工作示例:https://codesandbox.io/s/qqlyqwnm3j

containers / ProductForm.js

import React, { Component } from "react";
import { connect } from "react-redux";
import { submitDetails } from "../actions/";
import { browserHistory } from "react-router";

class ProductForm extends Component {
  state = {
    name: "",
    price: "",
    manufacturer: "",
    condition: "",
    manufactureDate: "",
    expirationDate: ""
  };

  handleChange = e => this.setState({ [e.target.name]: e.target.value });

  handleSubmit = e => {
    e.preventDefault();

    const {
      name,
      price,
      manufacturer,
      condition,
      manufactureDate,
      expirationDate
    } = this.state;
    if (
      !name ||
      !price ||
      !manufacturer ||
      !condition ||
      !manufactureDate ||
      !expirationDate
    )
      return;

    this.props.submitDetails({ ...this.state });
    browserHistory.push("/details");
  };

  render = () => (
    <div style={{ textAlign: "center" }} className="container">
      <form
        style={{ width: 400, margin: "0 auto" }}
        onSubmit={this.handleSubmit}
      >
        <h1 style={{ textAlign: "center" }}>Enter Product Details</h1>
        <div
          style={{ textAlign: "left", marginBottom: 20 }}
          className="form-group"
        >
          <label style={{ paddingLeft: 10 }}>Name</label>
          <input
            type="text"
            className="uk-input"
            name="name"
            placeholder="Name of product"
            onChange={this.handleChange}
            value={this.state.name}
          />
        </div>
        <div
          style={{ textAlign: "left", marginBottom: 20 }}
          className="form-group"
        >
          <label style={{ paddingLeft: 10 }}>Price</label>
          <input
            type="number"
            className="uk-input"
            name="price"
            placeholder="Product price"
            onChange={this.handleChange}
            value={this.state.price}
          />
        </div>
        <div
          style={{ textAlign: "left", marginBottom: 20 }}
          className="form-group"
        >
          <label style={{ paddingLeft: 10 }}>Manufacturer</label>
          <input
            type="text"
            className="uk-input"
            name="manufacturer"
            placeholder="Product manufacturer"
            onChange={this.handleChange}
            value={this.state.manufacturer}
          />
        </div>
        <div
          style={{ textAlign: "left", marginBottom: 20 }}
          className="form-group"
        >
          <label style={{ paddingLeft: 10 }}>Condition</label>
          <select
            name="condition"
            className="uk-select"
            value={this.state.condition}
            onChange={this.handleChange}
          >
            <option>Choose...</option>
            <option>New</option>
            <option>Used</option>
          </select>
        </div>
        <div
          style={{ textAlign: "left", marginBottom: 20 }}
          className="form-group "
        >
          <label style={{ paddingLeft: 10 }}>Manufacture Date</label>
          <input
            type="date"
            className="uk-input"
            name="manufactureDate"
            onChange={this.handleChange}
            value={this.state.manufactureDate}
          />
        </div>
        <div
          style={{ textAlign: "left", marginBottom: 20 }}
          className="form-group "
        >
          <label style={{ paddingLeft: 10 }}>Expiration Date</label>
          <input
            type="date"
            className="uk-input"
            name="expirationDate"
            onChange={this.handleChange}
            value={this.state.text}
          />
        </div>

        <button type="submit" className="uk-button uk-button-primary">
          Submit
        </button>
      </form>
    </div>
  );
}

export default connect(
  null,
  { submitDetails }
)(ProductForm);

containers / ShowDetails.js

import map from "lodash/map";
import isEmpty from "lodash/isEmpty";
import React from "react";
import { connect } from "react-redux";

const ShowDetails = ({ details }) =>
  isEmpty(details) ? (
    <div style={{ textAlign: "center", marginTop: 20 }}>
      <h3 style={{ color: "red" }}>No Products Found!</h3>
    </div>
  ) : (
    <div style={{ textAlign: "center" }}>
      <h1>Product Details </h1>
      <table style={{ marginBottom: 10 }} className="products">
        <thead className="thead-light">
          <tr>
            <th scope="col">Name</th>
            <th scope="col">Price</th>
            <th scope="col">Manufacturer</th>
            <th scope="col">Condition</th>
            <th scope="col">Manufacture Date</th>
            <th scope="col">Expiration Date</th>
          </tr>
        </thead>
        <tbody>
          {map(
            details,
            (
              {
                name,
                price,
                manufacturer,
                condition,
                manufactureDate,
                expirationDate
              },
              key
            ) => (
              <tr key={key}>
                <td>{name}</td>
                <td>${price}</td>
                <td>{manufacturer}</td>
                <td>{condition}</td>
                <td>{manufactureDate}</td>
                <td>{expirationDate}</td>
              </tr>
            )
          )}
        </tbody>
      </table>
    </div>
  );

export default connect(state => ({ details: state.product.details }))(
  ShowDetails
);

reducers / index.js

import { routerReducer as routing } from "react-router-redux";
import { combineReducers } from "redux";
import { ADD_PRODUCT } from "../types";

const productReducer = (state = { details: [] }, { type, payload }) => {
  switch (type) {
    case ADD_PRODUCT:
      return {
        ...state,
        details: [...state.details, payload]
      };
    default:
      return state;
  }
};

export default combineReducers({
  product: productReducer,
  routing
});

actions / index.js

import { ADD_PRODUCT } from "../types";

export const submitDetails = payload => ({
  type: ADD_PRODUCT,
  payload
});