reactjs - 从 react-redux 向后端 API 发送请求
问题描述
我的后端服务器是 NodeJs 连接到 MongoDB atlas,有一个名为companyorders的路由,它接受发布请求以使用户能够创建公司订单。我正在尝试通过 Redux 从反应应用程序发送发布请求。
这是我的代码...
Redux 商店
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(...middleware),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
export default store;
Redux 操作
import axios from 'axios';
import { GET_ERRORS, ADD_COMPANY_ORDER } from './types';
// Add Company Order
export const addCompanyOrder = (orderData) => (dispatch) => {
axios
.post('/api/companyorder/create', orderData)
.then((res) =>
dispatch({
type: ADD_COMPANY_ORDER,
payload: res.data,
})
)
.catch((err) =>
dispatch({
type: GET_ERRORS,
payload: err.response.data,
})
);
};
Redux 减速器
import { ADD_COMPANY_ORDER } from '../actions/types';
const initialState = {};
export default function addCompanyOrder(state = initialState, action) {
switch (action.type) {
case ADD_COMPANY_ORDER:
return {
...state,
initialState: action.payload,
};
default:
return state;
}
}
Redux 组合减速器
import { combineReducers } from 'redux';
import addCompanyOrder from './companyOrderReducer';
export default combineReducers({
co_order: addCompanyOrder,
});
反应组件
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import { addCompanyOrder } from '../../actions/companyOrderActions';
class Companyorder extends Component {
constructor(props) {
super(props);
this.state = {
orderName: '',
date: '',
orderQuantity: '',
orderSupplier: '',
orderCost: '',
oderTax: '',
supplierInfo: [
{
name: '',
location: '',
phone: '',
email: '',
},
],
oderReceived: '',
errors: {},
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
componentDidUpdate(nextProps) {
if (nextProps.errors) {
this.setState({ errors: nextProps.errors });
}
}
onSubmit(e) {
e.preventDefault();
const newOrder = {
orderName: this.state.orderName,
date: this.state.date,
orderQuantity: this.state.orderQuantity,
orderSupplier: this.state.orderSupplier,
orderCost: this.state.orderCost,
oderTax: this.state.oderTax,
name: this.state.name,
location: this.state.location,
phone: this.state.phone,
email: this.state.email,
};
this.props.addCompanyOrder(newOrder);
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
render() {
const { errors } = this.state;
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<Link to="/" className="btn btn-link">
<i className="fas fa-arrow-circle-left" /> Back To Dashboard
</Link>
</div>
</div>
<div className="card">
<div className="card-header"> Company Order Form</div>
<div className="card-body">
<div className="form-group row">
<label htmlFor="orderName" className="col-2 col-form-label">
Order Name
</label>
<div className="col-10">
<input
className="form-control"
type="text"
name="orderName"
minLength="2"
required
onChange={this.onChange}
value={this.state.orderName}
error={errors.orderName}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="date" className="col-2 col-form-label">
Order Date
</label>
<div className="col-10">
<input
className="form-control"
type="date"
name="date"
minLength="2"
required
onChange={this.onChange}
value={this.state.date}
error={errors.date}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="orderQuantity" className="col-2 col-form-label">
Order Quantity
</label>
<div className="col-10">
<input
className="form-control"
type="number"
name="orderQuantity"
minLength="2"
required
onChange={this.onChange}
value={this.state.orderQuantity}
error={errors.orderQuantity}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="orderSupplier" className="col-2 col-form-label">
Order Supplier
</label>
<div className="col-10">
<input
className="form-control"
type="text"
name="orderSupplier"
minLength="2"
required
onChange={this.onChange}
value={this.state.orderSupplier}
error={errors.orderSupplier}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="orderCost" className="col-2 col-form-label">
Order Cost
</label>
<div className="col-10">
<input
className="form-control"
type="text"
name="orderCost"
minLength="2"
required
onChange={this.onChange}
value={this.state.orderCost}
error={errors.orderCost}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="oderTax" className="col-2 col-form-label">
Order Tax
</label>
<div className="col-10">
<input
className="form-control"
type="text"
name="oderTax"
minLength="2"
required
onChange={this.onChange}
value={this.state.oderTax}
error={errors.orderTax}
/>
</div>
</div>
<div className="card-header">
<h5>Supplier info</h5>
<div className="card-body">
<div className="form-group row">
<label htmlFor="name" className="col-2 col-form-label">
Name
</label>
<div className="col-10">
<input
className="form-control"
type="text"
name="name"
minLength="2"
required
onChange={this.onChange}
value={this.state.name}
error={errors.name}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="location" className="col-2 col-form-label">
Location
</label>
<div className="col-10">
<input
className="form-control"
type="text"
name="location"
minLength="2"
required
onChange={this.onChange}
value={this.state.location}
error={errors.loaction}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="phone" className="col-2 col-form-label">
Phone
</label>
<div className="col-10">
<input
className="form-control"
type="text"
name="phone"
minLength="2"
required
onChange={this.onChange}
value={this.state.phone}
error={errors.phone}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="email" className="col-2 col-form-label">
Email
</label>
<div className="col-10">
<input
className="form-control"
type="text"
name="email"
minLength="2"
required
onChange={this.onChange}
value={this.state.email}
error={errors.email}
/>
</div>
</div>
</div>
</div>
<input
type="submit"
value="Submit"
className="btn btn-primary btn-block"
/>
</div>
</div>
</div>
);
}
}
Companyorder.propTypes = {
addCompanyOrder: PropTypes.func.isRequired,
co_order: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
co_order: state.co_order,
errors: state.errors,
});
export default connect(mapStateToProps, { addCompanyOrder })(
withRouter(Companyorder)
);
代码编译成功,但是 redux 没有发出任何请求,甚至没有填充 redux 状态。如果知道错误或更好的方法,请留下您的回复,我非常感谢。
解决方案
似乎您没有onSubmit
在代码中的任何地方调用您的处理程序。您可能应该用form
标签包装您的表单并将 onSubmit 属性设置为您的处理程序函数。
<form onSubmit={this.onSubmit}>
...
</form>
顺便说一句,您的减速器似乎不正确。在我看来,您可能想要更类似的东西:
import { ADD_COMPANY_ORDER } from '../actions/types';
const initialState = {
co_orders: []
};
export default function addCompanyOrder(state = initialState, action) {
switch (action.type) {
case ADD_COMPANY_ORDER:
const newCoOrder = action.payload;
return {
co_orders: [...state.co_orders, newCoOrder];
};
default:
return state;
}
}
如果您的应用程序复杂性增加,其他不相关的提示:
- 考虑使用某种不可变库,例如Immer或ImmutableJS(我会选择第一个)。参考:https ://redux.js.org/recipes/using-immutablejs-with-redux/#using-immutablejs-with-redux
- 考虑编写选择器以从您的 redux 状态中获取数据,并且可能使用重新选择库。参考:https ://redux.js.org/recipes/computing-derived-data/
- 如果您的应用程序中有许多表单,请考虑使用表单库,这将使您的生活更轻松(Formik,react-final-form或react-hook-form等)
推荐阅读
- ssas - MDX:过滤掉零值
- python - 如何在 SPARQL 本体查询中使用 python 变量?
- java - 如何在android webview中实现onback()的进度条
- laravel - 在 Laravel 的模板中未加载 CSS 和 JS
- flutter - 如何在appbar底部定位线性进度条?
- javascript - 使用 Ramda,你如何组合二进制函数?
- puppeteer-sharp - 是否可以使用 puppeteeter sharp 将部分网页转换为 PDF?
- swift - 用于时间序列分析的 Core ML
- vb.net - 3d坐标系中两点之间的间距
- python - 使用 psycopg2 复制到带有 ARRAY INT 列的表