【发布时间】:2021-06-11 10:41:10
【问题描述】:
左边的项目是固定的,不会改变。它与右侧的物品一起包装,客户可以在其中选择滑雪板:
我所需要的只是当客户选择一个尺寸,然后滑动到下一个滑雪板时,从前一个滑雪板中选择的尺寸将被设置回默认的“选择尺寸选项”。
这是父组件的代码:
import React, { useState, useEffect } from 'react';
// Material UI
import { makeStyles } from '@material-ui/core/';
// React Responsive Carousel
import { Carousel } from 'react-responsive-carousel';
import '../../../../../../node_modules/react-responsive-carousel/lib/styles/carousel.min.css'
// Component
import PackageProd from './PackageProd/packageProd';
const useStyles = makeStyles({
packageCard: {
maxWidth: 345,
height: '100%'
},
});
const Packages = (props) => {
const classes = useStyles();
const [defaultProd, setDefaultProd] = useState({ size: 'CHOOSE THE SIZE', discount: '0', price: '0', barcode: 'default' });
function handleSetProd(val){
setDefaultProd(val)
}
return <Carousel className={classes.packageCard} showIndicators={false}
renderItem={item => <div style={{ background: "white", height: '100%' }}>{item}</div>}
onChange={(val)=>{
setDefaultProd({ size: 'CHOOSE THE SIZE', discount: '0', price: '0', barcode: 'default' })
}}
>
{props._packages.map((prod, i)=>{
return <PackageProd
key={i}
_prod={prod}
_handleSetProd={handleSetProd}
_defaultProd={defaultProd}
></PackageProd>
})}
</Carousel>
}
export default Packages;
我正在使用一个 npm 包 Carousel,它带有一个内置方法 onChange,每次滑动都会触发。因此,每次我滑动到下一个滑雪板或上一个滑雪板时,它都会设置 defaultProd。
这是子组件:
import React, { useEffect, useState } from 'react';
// Material UI
import { makeStyles, Grid, Card, CardContent, CardMedia,
Typography, CardActions, Button, FormControl, InputLabel,
Select, } from '@material-ui/core/';
import { display } from '@material-ui/system';
// React Router
import { Link } from "react-router-dom";
// Knight Demon
import knightDemon from '../../../../../../assets/icons/knight_demon.png';
// Price Format
const { format } = require('number-currency-format');
const useStyles = makeStyles({
sizes: {
minWidth: '100%'
},
media: {
height: '20rem',
objectFit: 'contain'
},
text: {
color: 'black'
},
price: {
color: 'green'
},
redPrice: {
color: 'red',
textDecoration: 'line-through'
},
});
const PackageProd = (props) => {
const classes = useStyles();
const [prodDetails, setProdDetails] = useState({});
const handleChange = (event) => {
var specificProd = JSON.parse(event.target.value)
props._handleSetProd(specificProd)
};
const PriceWithDiscount = () => <Grid container direction='row' justify='center' spacing={2}>
<Grid item>
<span className={classes.redPrice}>
{format(props._defaultProd.price, {
currency: 'isk',
showDecimals: 'NEVER',
thousandSeparator: ' '
})}
</span>
</Grid>
<Grid item>
<span className={classes.price}>
{format(Math.ceil(parseInt(props._defaultProd.price) - (parseInt(props._defaultProd.price) * props._defaultProd.discount / 100)), {
currency: 'isk',
showDecimals: 'NEVER',
thousandSeparator: ' '
})}
</span>
</Grid>
</Grid>
const PriceWithoutDiscount = () => <span className={classes.price}>
{format(props._defaultProd.price, {
currency: 'isk',
showDecimals: 'NEVER',
thousandSeparator: ' '
})}
</span>
return <div>
<CardMedia
className={classes.media}
component='img'
image={props._prod.images.length > 0 ? props._prod.images[0] : knightDemon}
/>
<CardContent>
<Link to={`/product?id=${props._prod._id}`}>
<Typography className={classes.text} variant='h5' component='h2' onClick={()=>console.log(props._prod)}>
{props._prod.description}
</Typography>
</Link>
{props._defaultProd.discount > 0 ?
<PriceWithDiscount></PriceWithDiscount> :
<PriceWithoutDiscount></PriceWithoutDiscount>
}
</CardContent>
<CardActions>
{props._prod.sizepricesdiscountqty.length >= 1 &&
props._prod.sizepricesdiscountqty[0].size !== '' ?
<FormControl className={classes.sizes}>
<InputLabel htmlFor='age-native-simple'>SIZE</InputLabel>
<Select
native
defaultValue={props._defaultProd.size}
onChange={handleChange}
inputProps={{
name: 'prodDetails',
id: 'age-native-simple',
}}
>
<option value={JSON.stringify(props._defaultProd)}>CHOOSE SIZE</option>
{props._prod.sizepricesdiscountqty.map((item, i)=>{
if(parseInt(item.qty) > 0){
return <option key={i}
value={JSON.stringify(item)}
>
{item.size.toUpperCase()}
</option>
}
})}
</Select>
</FormControl> :
<Grid container justify='flex-start'>
{props._prod.sizepricesdiscountqty[0].size === '' ?
<Typography>SIZE: NO SIZE</Typography> :
<Typography>SIZE: {props._prod.sizepricesdiscountqty[0].size.toUpperCase()}</Typography>
}
</Grid>
}
</CardActions>
</div>
}
export default PackageProd;
我不明白的行为是材料选择组件的默认值。当我记录从父级传递的 defaultProd 时,它具有它假设的所有值。当我选择不同的大小时,它会更改它并将父级中的 defaultProd 设置为新对象。
问题是当我滑动到新产品时,它应该将 defaultValue 更改为 defaultProd 的大小值,但它没有。更改反映在价格中,控制台正确记录了 defaultProd,但大小没有更改为“选择大小”,我不知道为什么它没有反映应有的更改。这是视觉示例:
然后我滑到下一个滑雪板并滑回上一个。价格反映变化。 defaultProd 被正确记录,但大小没有改变:
到目前为止,我尝试的是尝试强制重新渲染:
const [, updateState] = useState();
const forceUpdate = useCallback(() => updateState({}), []);
并在子组件的 useEffect() 中触发它们。我尝试使用value 而不是defaultValue,但是在更改大小时它不起作用,只会一直显示CHOOSE SIZE。在这一点上,我不明白材料选择中的 defaultValue 是如何工作的,以及为什么它不反映变化。
【问题讨论】:
标签: reactjs select react-hooks material-ui