React中如何实现列表项高度从固定300px动态设置为auto?
问题原因
- 你更新
expandedArray状态时直接修改了原数组引用,React状态更新依赖引用变化判断是否重渲染,原数组引用没有改变的情况下,组件不会触发重新渲染,高度自然不会更新。 - 展开按钮放在了设置
overflow: hidden的内部容器中,当内容高度超过300px时,按钮会被截断隐藏,无法触发点击事件。
修正方案
- 修改状态更新逻辑,每次更新创建新的数组,保证引用变化触发重渲染
- 将展开按钮移动到固定高度的容器外部,保证按钮始终可见
- 可选优化:可以先判断内容实际高度是否小于300px,若不足则直接隐藏展开按钮,避免无意义的交互
修正后代码
const IndexPage: React.FC<IndexPageProps> = ({}) => { const classes = useStyles(); const [{ data, fetching }] = useGetGroupsQuery(); const [expandedArray, setExpandedArray] = useState<number[]>([]); const handleExpandClick = (id: number) => { // 直接创建新数组,不修改原state引用 setExpandedArray(prev => [...prev, id]); }; const getHeight = (id: number) => { if (!expandedArray.includes(id)) { return { height: 300 }; } else { return { height: "auto" }; } }; return ( <Layout variant="regular"> {!fetching && data ? ( <Grid container direction="column" spacing={2}> {data.groups.map((group) => { return ( <Grid xs={12} item key={group.id}> <Paper> <Box className={classes.paddedBox}> {/* 高度控制的容器只包裹内容,不放展开按钮 */} <Box overflow="hidden" style={getHeight(group.id)}> <NextLink href="/class/cliques/[group.slug]" as={`/class/cliques/${group.slug}`} > <Typography variant="h4" className={classes.groupName}> <Link color="inherit">{group.name}</Link> </Typography> </NextLink> <Typography variant="h5">Description</Typography> <Typography className={classes.preline}> {group.description} </Typography> <Typography variant="h5">Requirements</Typography> <Typography className={classes.preline}> {group.requirements} </Typography> </Box> {/* 展开按钮移到外层 */} <Box className={classes.expandMoreBlock} onClick={() => handleExpandClick(group.id)} > <IconButton className={classes.expandMore}> <ExpandMoreRounded /> </IconButton> </Box> </Box> </Paper> </Grid> ); })} </Grid> ) : null} </Layout> ); };
额外说明
如果需要加展开收起的过渡动画,不要直接用height: auto,可以换成动态设置max-height属性,从300px改为一个足够容纳内容的固定值(比如2000px),就可以实现平滑的过渡效果。
内容的提问来源于stack exchange,提问作者JunKang Ng
相关产品推荐
相关产品推荐

