React Render List Incorrect(列表正确,但渲染覆盖和重复)
React Render List Incorrect (List is correct, but render overwrite and duplicate)
我正在尝试做一个简单的订单系统,当用户选择数量并点击“添加到订单”时,所选菜品的信息将显示在“您的订单”区域(点击“刷新订单”查看)。我正在做的是将菜肴信息(来自 MenuEdit 组件)插入到列表(在 CustomerOrder 组件中)。
我的问题如下:我在订单中添加“Moo Goo Guy Pan”QTY:1,它会被插入到列表中,然后我添加“Teriyaki Chicken”QTY:2,它将被插入到列表中,我再次添加“Moo Goo Guy Pan”但是 QTY:3 订购,它将被插入到列表中。 uid 是用户点击“Add to Order”时的时间戳。该列表工作正常(我使用 lodash 进行深度复制),但是当渲染列表的所有项目时效果不佳。我想不出解决它的正确方法。我愿意根据您的要求提供更多信息。感谢您的宝贵时间和帮助。
我制作了一个 GIF 来演示该步骤,您可以在控制台中看到列表的变化。
link: https://github.com/Dungyichao/COVID19_Reporting_Web/blob/master/img/EggrollChenOrderSC.gif
用户点击“Add to Order”,第一步和第二步都很好。
购物车(您的订单)的渲染步骤,第一步和第二步都很好。
以下是传递给组件进行渲染的列表。请注意数量不同,这是我想要的正确列表,并且已经传递到 CartList 组件中。
我的代码和组件结构如下
Order.js
export default class CustomerOrder extends Component {
constructor(props) {
super(props);
this.firebase = props.firebase;
this.sendinfo_toCart_handle = this.sendinfo_toCart_handle.bind(this);
this.Cart_new_item_arrive = this.Cart_new_item_arrive.bind(this);
this.remove_item = this.remove_item.bind(this);
this.state = {
Cart_data: [],
Cart_new_item: '',
}
this.refresh_cart_handle = this.refresh_cart_handle.bind(this);
}
remove_item(e){
console.log("Remove item uid: ", e);
}
refresh_cart_handle(){
let {Cart_data} = this.state;
console.log("Current Cart Data: ", Cart_data);
}
Cart_new_item_arrive(e){
//console.log("Cart_new_item_arrive: ", e);
this.setState({Cart_new_item: e}, () => {
//after setstate
this.sendinfo_toCart_handle();
});
}
sendinfo_toCart_handle(){
let {Cart_new_item, Cart_data} = this.state;
let deepcopy_list = _.cloneDeep(Cart_data);
deepcopy_list.push(Cart_new_item);
this.setState({Cart_data: deepcopy_list});
}
render() {
let {Cart_data} = this.state;
return (
<div style={order_style}>
<div style={{
}}>
<h3>Menu</h3>
<MenuEdit firebase={this.firebase} CartAdd={this.Cart_new_item_arrive} />
</div>
<div style={{
}}>
<h3>Your Order</h3>
<Cart data_array={Cart_data} remove_item={this.remove_item} /> {/*remove_item={this.remove_item}*/}
<Button onClick={this.refresh_cart_handle}>Refresh Order</Button>
</div>
</div>
);
}
}
Cart.js
export default class Cart extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div>
<Scroll>
<CartList data_array={this.props.data_array} remove_item={this.props.remove_item} /> {/*remove_item={this.props.remove_item}*/}
</Scroll>
</div>
<div>
<div><Button>Refresh</Button></div>
<div>
<Button>Cancel</Button> {' '}
<Button>Place Order</Button>
</div>
</div>
</div>
);
}
}
CartList.js
export default class CartList extends Component {
constructor(props) {
super(props);
}
render(){
let display_data = this.props.data_array;
let null_page = [];
console.log("Data in CartList.js: ", display_data)
if(display_data[0]){
return(
display_data.map(
(cart_item, idx) => {
//console.log("In Map", idx, ' Item: ', cart_item);
return(
<div>
<CartItem key={idx} u_key={idx + 1}
Cart_item_info={cart_item}
remove_item={this.props.remove_item} /> {/*remove_item={this.props.remove_item}*/}
</div>
);
}
)
)
}
else{
return(
<div>
<p>Add Your Favorite Dishes to Here</p>
</div>
);
}
}
}
CartItem.js(呈现列表中的每个项目)
export default class CartItem extends Component {
constructor(props) {
super(props);
this.state = {
show_toggle: true,
cart_item_info: this.props.Cart_item_info,
u_key: this.props.u_key,
}
//cart_item_info: this.props.Cart_item_info,
this.remove_item_handle = this.remove_item_handle.bind(this);
}
remove_item_handle(){
let {cart_item_info} = this.state;
this.props.remove_item(cart_item_info.uid);
}
render() {
let {cart_item_info, u_key} = this.state;
//console.log("Return CartItem")
return (
<div key={u_key} >
<Accordion>
<Card>
<Accordion.Toggle as={Card.Header} eventKey="0">
<div style={item_style}>
<div style={{flex: '1'}}>{u_key}.</div>
<div style={{flex: '7'}}> {cart_item_info.dish_name}</div>
<div style={{flex: '2'}}>X {cart_item_info.qty}</div>
<div style={{flex: '2'}}>${cart_item_info.Tprice}</div>
</div>
</Accordion.Toggle>
<Accordion.Collapse eventKey="0">
<Card.Body>
<Button onClick={this.remove_item_handle} >Remove</Button>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</div>
);
}
}
更新您的 cartItem.js 文件。它应该是功能组件。
const CartItems = (props) => {
console.log(props.Cart_item_info);
return (
<div key={props.u_key} >
<Accordion>
<Card>
<Accordion.Toggle as={Card.Header} eventKey="0">
<div>
<div style={{ flex: '1' }}>{props.u_key}.</div>
<div style={{ flex: '7' }}> {props.Cart_item_info.dish_name}</div>
<div style={{ flex: '2' }}>X {props.Cart_item_info.qty}</div>
<div style={{ flex: '2' }}>${props.Cart_item_info.Tprice}</div>
</div>
</Accordion.Toggle>
<Accordion.Collapse eventKey="0">
<Card.Body>
<div>No</div>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</div>
);
}
我终于找到了问题的根本原因,但我没有在问题中透露它,因为我什至认为这不会导致问题
问题出在 MenuItem 组件(用户可以单击添加到订单的菜单项)。正确的方法是清除所有数据(将要插入 Order.js 中的列表)在 MenuItem 组件已经插入的状态下保留。通过这样做,您可以防止再次发送任何原始数据。
同样在与 Deepak 的聊天室中,他提出了以下一些提示:
- 当你只想展示一些东西而不需要状态管理时,你更喜欢功能组件。
- 键有助于识别列表中的项目更改。
我正在尝试做一个简单的订单系统,当用户选择数量并点击“添加到订单”时,所选菜品的信息将显示在“您的订单”区域(点击“刷新订单”查看)。我正在做的是将菜肴信息(来自 MenuEdit 组件)插入到列表(在 CustomerOrder 组件中)。
我的问题如下:我在订单中添加“Moo Goo Guy Pan”QTY:1,它会被插入到列表中,然后我添加“Teriyaki Chicken”QTY:2,它将被插入到列表中,我再次添加“Moo Goo Guy Pan”但是 QTY:3 订购,它将被插入到列表中。 uid 是用户点击“Add to Order”时的时间戳。该列表工作正常(我使用 lodash 进行深度复制),但是当渲染列表的所有项目时效果不佳。我想不出解决它的正确方法。我愿意根据您的要求提供更多信息。感谢您的宝贵时间和帮助。
我制作了一个 GIF 来演示该步骤,您可以在控制台中看到列表的变化。 link: https://github.com/Dungyichao/COVID19_Reporting_Web/blob/master/img/EggrollChenOrderSC.gif
用户点击“Add to Order”,第一步和第二步都很好。
购物车(您的订单)的渲染步骤,第一步和第二步都很好。
以下是传递给组件进行渲染的列表。请注意数量不同,这是我想要的正确列表,并且已经传递到 CartList 组件中。
我的代码和组件结构如下
Order.js
export default class CustomerOrder extends Component {
constructor(props) {
super(props);
this.firebase = props.firebase;
this.sendinfo_toCart_handle = this.sendinfo_toCart_handle.bind(this);
this.Cart_new_item_arrive = this.Cart_new_item_arrive.bind(this);
this.remove_item = this.remove_item.bind(this);
this.state = {
Cart_data: [],
Cart_new_item: '',
}
this.refresh_cart_handle = this.refresh_cart_handle.bind(this);
}
remove_item(e){
console.log("Remove item uid: ", e);
}
refresh_cart_handle(){
let {Cart_data} = this.state;
console.log("Current Cart Data: ", Cart_data);
}
Cart_new_item_arrive(e){
//console.log("Cart_new_item_arrive: ", e);
this.setState({Cart_new_item: e}, () => {
//after setstate
this.sendinfo_toCart_handle();
});
}
sendinfo_toCart_handle(){
let {Cart_new_item, Cart_data} = this.state;
let deepcopy_list = _.cloneDeep(Cart_data);
deepcopy_list.push(Cart_new_item);
this.setState({Cart_data: deepcopy_list});
}
render() {
let {Cart_data} = this.state;
return (
<div style={order_style}>
<div style={{
}}>
<h3>Menu</h3>
<MenuEdit firebase={this.firebase} CartAdd={this.Cart_new_item_arrive} />
</div>
<div style={{
}}>
<h3>Your Order</h3>
<Cart data_array={Cart_data} remove_item={this.remove_item} /> {/*remove_item={this.remove_item}*/}
<Button onClick={this.refresh_cart_handle}>Refresh Order</Button>
</div>
</div>
);
}
}
Cart.js
export default class Cart extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div>
<Scroll>
<CartList data_array={this.props.data_array} remove_item={this.props.remove_item} /> {/*remove_item={this.props.remove_item}*/}
</Scroll>
</div>
<div>
<div><Button>Refresh</Button></div>
<div>
<Button>Cancel</Button> {' '}
<Button>Place Order</Button>
</div>
</div>
</div>
);
}
}
CartList.js
export default class CartList extends Component {
constructor(props) {
super(props);
}
render(){
let display_data = this.props.data_array;
let null_page = [];
console.log("Data in CartList.js: ", display_data)
if(display_data[0]){
return(
display_data.map(
(cart_item, idx) => {
//console.log("In Map", idx, ' Item: ', cart_item);
return(
<div>
<CartItem key={idx} u_key={idx + 1}
Cart_item_info={cart_item}
remove_item={this.props.remove_item} /> {/*remove_item={this.props.remove_item}*/}
</div>
);
}
)
)
}
else{
return(
<div>
<p>Add Your Favorite Dishes to Here</p>
</div>
);
}
}
}
CartItem.js(呈现列表中的每个项目)
export default class CartItem extends Component {
constructor(props) {
super(props);
this.state = {
show_toggle: true,
cart_item_info: this.props.Cart_item_info,
u_key: this.props.u_key,
}
//cart_item_info: this.props.Cart_item_info,
this.remove_item_handle = this.remove_item_handle.bind(this);
}
remove_item_handle(){
let {cart_item_info} = this.state;
this.props.remove_item(cart_item_info.uid);
}
render() {
let {cart_item_info, u_key} = this.state;
//console.log("Return CartItem")
return (
<div key={u_key} >
<Accordion>
<Card>
<Accordion.Toggle as={Card.Header} eventKey="0">
<div style={item_style}>
<div style={{flex: '1'}}>{u_key}.</div>
<div style={{flex: '7'}}> {cart_item_info.dish_name}</div>
<div style={{flex: '2'}}>X {cart_item_info.qty}</div>
<div style={{flex: '2'}}>${cart_item_info.Tprice}</div>
</div>
</Accordion.Toggle>
<Accordion.Collapse eventKey="0">
<Card.Body>
<Button onClick={this.remove_item_handle} >Remove</Button>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</div>
);
}
}
更新您的 cartItem.js 文件。它应该是功能组件。
const CartItems = (props) => {
console.log(props.Cart_item_info);
return (
<div key={props.u_key} >
<Accordion>
<Card>
<Accordion.Toggle as={Card.Header} eventKey="0">
<div>
<div style={{ flex: '1' }}>{props.u_key}.</div>
<div style={{ flex: '7' }}> {props.Cart_item_info.dish_name}</div>
<div style={{ flex: '2' }}>X {props.Cart_item_info.qty}</div>
<div style={{ flex: '2' }}>${props.Cart_item_info.Tprice}</div>
</div>
</Accordion.Toggle>
<Accordion.Collapse eventKey="0">
<Card.Body>
<div>No</div>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</div>
);
}
我终于找到了问题的根本原因,但我没有在问题中透露它,因为我什至认为这不会导致问题
问题出在 MenuItem 组件(用户可以单击添加到订单的菜单项)。正确的方法是清除所有数据(将要插入 Order.js 中的列表)在 MenuItem 组件已经插入的状态下保留。通过这样做,您可以防止再次发送任何原始数据。
同样在与 Deepak 的聊天室中,他提出了以下一些提示:
- 当你只想展示一些东西而不需要状态管理时,你更喜欢功能组件。
- 键有助于识别列表中的项目更改。