问题:
我的应用程序的第一页显示销售发票列表。
我选择一个运行以单击发票的ID作为参数的函数,并通过API调用获取其详细信息。
由Customer
渲染的 SaleInvoice
组件具有一个输入框(“预定义”组件),该输入框应显示customerName
从SaleInvoice
传递而来,但操作不正确。有时为空白,当我返回首页(销售发票清单)并选择其他销售发票时,即先前销售发票的customerName
。我检查了控制台日志(请参阅<React.Fragment>
组件中Customer
之后的行),并且在减速器显示的状态下可以看到customerName的正确值。
最初,SaleInvoice是有状态组件,但没有状态对象。我将状态设为通过componentWillMount
中的API来获取数据。由于上述问题,我尝试了以下方法:
在customerName
的状态下添加了SaleInvoice
在客户道具中将this.props.customerName
更改为this.state.customerName
已使用
getDerivedStateFromProps()
说我不能使用componentWillMount
还尝试了shouldComponentUpdate
和其他一些东西。
什么都没有。请帮助。如果需要发布更多代码,请告诉我。
减速器的相关切片
case actionTypes.INVOICE_BY_ID_SUCCESS:
let customerData = action.payload[0];
let saleInvoiceData = action.payload[1];
let newState = Object.assign({}, state);
newState.loading = false;
newState.error = null;
newState.customerInfo = {
...state.customerInfo,
id: customerData.id,
place: customerData.place,
addressLineOne: customerData.address_line_one,
};
newState.saleInvoiceId = saleInvoiceData.id;
newState.customerName = saleInvoiceData.customer_name;
newState.serialNumber = saleInvoiceData.serial_number;
newState.amountBeforeFreight = saleInvoiceData.amount_before_freight;
newState.freight = saleInvoiceData.freight;
newState.amountAfterFreight = saleInvoiceData.amount_after_freight;
return newState;
SaleInvoiceContainer.js(不包括进口商品)
const mapStateToProps = (state, ownProps) => {
console.log(`ownProps ${ownProps}`);
console.log(ownProps);
return {
customerLoading: state.saleInvoiceReducer.customerLoading,
customerError: state.saleInvoiceReducer.customerError,
productError: state.lineItemsReducer.error,
productLoading: state.lineItemsReducer.loading,
saleInvoiceError: state.saleInvoiceReducer.error,
saleInvoiceLoading: state.lineItemsReducer.error,
saleInvoiceId: state.saleInvoiceReducer.saleInvoiceId,
customerData: state.saleInvoiceReducer.customerData, // data of all customers
productData: state.lineItemsReducer.productData, // data of all products
customerInfo: state.saleInvoiceReducer.customerInfo, // data of current customer
addingCustomer: state.saleInvoiceReducer.addingCustomer, // modal show/hide
customerName: state.saleInvoiceReducer.customerName, // input field name
grandTotal: subTotalSelector(state),
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
return {
fetchCustomer: () => dispatch(fetchCustomer()),
fetchProduct: () => dispatch(fetchProduct()),
getInvoiceById: () =>
dispatch(getInvoiceById(ownProps.location.state.id)),
onBlurCustomerName: event => dispatch(onBlurCustomerName(event)),
stopAddingCustomer: () => dispatch(stopAddingCustomer()),
};
};
const SaleInvoiceContainer = connect(
mapStateToProps,
mapDispatchToProps,
)(SaleInvoice);
SaleInvoice.js(不包括进口商品)
class SaleInvoice extends React.Component {
state = {
customerName: '',
};
componentWillMount() {
// if api is called from here, state will not update when api updates
// props change cause re-render
this.props.getInvoiceById();
this.props.fetchCustomer();
this.props.fetchProduct();
}
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.customeName !== prevState.customerName) {
return {customerName: nextProps.customerName};
} else return null;
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.customerName !== this.state.customerName) {
let customerName = this.state.customerName;
//Perform some operation here
this.setState({customerName});
}
}
render() {
console.log(this.props);
let ui = this.props.customerError ? (
<p>Customers failed to load!</p>
) : (
<Spinner />
);
let printLink = '/sale-invoice/' + this.props.saleInvoiceId + '/print';
let sui = this.props.productError ? (
<p>Products failed to load!</p>
) : (
<Spinner />
);
if (
!this.props.customerLoading &&
!this.props.customerError &&
!this.props.error
) {
console.log('Customers have been loaded');
ui = (
<React.Fragment>
<Modal
show={this.props.addingCustomer}
modalClosed={this.props.stopAddingCustomer}
customerData={this.props.customerData}
name={this.state.customerName}
/>
<div className={classes.mainContainerTitle}>
{console.log(this.props.grandTotal)}
<h5 className={classes.pageTitle}>Sale Invoice</h5>
<NavLink className={classes.NavLink} to={printLink}>
Print
</NavLink>
{/*<button>Print</button>*/}
</div>
<rs.Container
fluid
className={[classes.mainContainer, classes.containerFluid].join(
'',
)}>
<rs.Row className={classes.firstRow}>
<Customer
customerData={this.props.customerData}
onBlurCustomerName={this.props.onBlurCustomerName}
customerInfo={this.props.customerInfo}
customerName={this.state.customerName}
/>
<SaleInvoiceSummary grandTotal={this.props.grandTotal} />
</rs.Row>
</rs.Container>
</React.Fragment>
);
}
if (
!this.props.productLoading &&
!this.props.productError &&
!this.props.error
) {
console.log('Products have been loaded');
sui = (
<React.Fragment>
<rs.Container fluid className={classes.gridContainer}>
<LineItemsContainer />
</rs.Container>
</React.Fragment>
);
}
return (
<React.Fragment>
{ui}
{sui}
</React.Fragment>
);
}
}
Customer.js(不包括导入)
const Customer = props => {
function _renderMenuItemChildren(option, props, index) {
return [
<Highlighter key="name" search={props.text}>
{option.name}
</Highlighter>,
<div key="place">
<small>Place: {option.place}</small>
</div>,
];
}
return (
<React.Fragment>
{console.log(props.customerName)}
<rs.Card col="sm-4" className={classes.firstCard}>
<rs.CardHeader className={classes.cardHeader}>
Customer Details
</rs.CardHeader>
<rs.CardBody className={classes.cardBodySaleInvoice}>
<rs.Label>Name</rs.Label>
<React.Fragment>
<Typeahead
className={classes.customerTypeahead}
defaultInputValue={props.customerName}
allowNew={true}
newSelectionPrefix="Add New: "
disabled={false}
labelKey="name" // this determines what array key value to show
multiple={false}
options={props.customerData}
placeholder="Choose a customer..."
onBlur={event => props.onBlurCustomerName(event)}
renderMenuItemChildren={_renderMenuItemChildren}
/>
<rs.FormGroup />
</React.Fragment>
<div className={classes.customerCardBody}>
<rs.Label>Address</rs.Label>
<div className={classes.address}>
{props.customerInfo.addressLineOne}
<br />
{props.customerInfo.addressLineTwo}
<br />
{props.customerInfo.address_line_three}
<br />
{props.customerInfo.contact_no_one}
<br />
{props.customerInfo.gst_number}
<br />
<button>Edit</button>
</div>
</div>
</rs.CardBody>
</rs.Card>
</React.Fragment>
);
};
(PS:我是React的新手,对代码的其他评论/批评将很有帮助)
答案 0 :(得分:0)
我添加了一个html输入组件,并发现它可以正常工作。
问题出在Typeahead
组件上。
https://github.com/fmoo/react-typeahead/issues/74#issuecomment-112552406
此外,现在使用react-select
代替Typeahead
,它也可以正常工作。