You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何控制MUI List自动滚动,解决聊天场景消息被输入框遮挡问题

实现方案

1. 修复布局溢出问题

外层采用flex垂直布局占满整个视口,让中间聊天区域自动填充剩余高度,List组件限制滚动范围,避免内容溢出到输入框区域:

  1. 最外层容器添加flex布局样式,固定高度为100vh,禁止整体溢出
  2. 包裹标题和List的中间容器设置flex:1,自动占满头部和底部输入框之间的空间
  3. List组件添加纵向滚动属性,内容超出高度时自动出现滚动条

对应代码修改点:

// 最外层div修改
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh', overflow: 'hidden' }}>
  <CssBaseline />
  {/* 中间容器修改 */}
  <div className={classes.section} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
    <Typography variant="h5" gutterBottom component="div" sx={{ p: 2, pb: 0 }}>
      Inbox
    </Typography>
    {/* List组件修改 */}
    <List 
      sx={{ 
        mb: 2, 
        flex: 1, 
        overflowY: 'auto',
        overscrollBehavior: 'contain' // 避免滚动时触发父容器回弹
      }}
    >
      {/* 原有ListItem逻辑不变 */}
    </List>
  </div>
  {/* 底部输入框原有逻辑不变 */}
</div>

如果需要固定List的最大高度,只需要把List的flex:1替换为maxHeight: 'calc(100vh - 180px)'即可,数值根据自身头部、底部的实际高度调整。


2. 实现新消息自动滚动到底部

配合React的ref和副作用监听,每次消息列表更新时自动滚动到最底部:

  1. 引入对应Hook:
import { useRef, useEffect } from 'react'
  1. 组件内定义List的ref和滚动副作用:
const listRef = useRef(null)

// 监听messages变化,自动滚动到底部
useEffect(() => {
  listRef.current?.scrollTo(0, listRef.current.scrollHeight)
}, [messages])
  1. 将ref绑定到List组件:
<List ref={listRef} {/* 其他原有属性 */}>

修改后完整代码

import { useRef, useEffect } from 'react'
// 其他原有导入不变

// 组件内部逻辑
const YourChatComponent = () => {
  // 原有state、函数逻辑不变
  const listRef = useRef(null)

  useEffect(() => {
    listRef.current?.scrollTo(0, listRef.current.scrollHeight)
  }, [messages])

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100vh', overflow: 'hidden' }}>
      <CssBaseline />
      <div className={classes.section} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
        <Typography variant="h5" gutterBottom component="div" sx={{ p: 2, pb: 0 }}>
          Inbox
        </Typography>
        <List 
          ref={listRef}
          sx={{ 
            mb: 2, 
            flex: 1, 
            overflowY: 'auto',
            overscrollBehavior: 'contain'
          }}
        >
          {messages.map( (item) => (
            <ListItem button key ={item.id} ref={messageRef}>
              <ListItemAvatar>
                <Avatar alt="Profile Picture"  />
              </ListItemAvatar>
              <ListItemText  primary={item.content} secondary={item.sender} />
            </ListItem>
          ))}
        </List>
      </div>
      <paperClasses className= {classes.footer}>
        <div style={{marginLeft: 'calc(1%)', backgroundColor: '#f1f3f4', borderRadius: '25px'}}>
          <Controls.Input 
            name = "message"
            label= "Send message"
            value= {message}
            onChange={onChangeHandler}
            InputProps={{
              disableUnderline: true,
            }}
          />
          <Controls.Button
            onClick={sendMessage}
            text="Send"
          />
        </div>
      </paperClasses>
    </div>
  );
}

内容的提问来源于stack exchange,提问作者DrDoggo。

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 01:48:02