我正在尝试收集有关组件的一些详细信息,并在短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 }
}
答案 0 :(得分:2)
好的,有很多调整,但总结一下:
this.setState()
调用都应使用类方法进行。connect()
需要2个参数:mapStateToProps
和mapDispatchToProps
...如果不使用mapStateToProps
,则必须传入null
作为第一个参数。 / li>
<input name="name" value={this.state.name} onChange={this.handleChange} />
。既不需要也不建议使用输入id
。在这种情况下,this.handleChange
利用e.target.name
和e.target.value
来跟踪输入及其值。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
});