ReactJS中使用Mobx Observer展示MUI Snackbar失效问题排查
问题分析与解决方案
核心问题1:Mobx 6+ 未初始化响应式
在Mobx 6及以上版本中,使用@observable、@action、@computed这类装饰器语法时,必须在类的构造函数中调用makeObservable(this)来启用响应式能力。你的AlertsStore没有构造函数,也未执行初始化操作,导致所有装饰器完全不生效——Mobx无法追踪alerts数组的变化,@observer组件自然不会触发重渲染。
核心问题2:push逻辑导致current指向旧的隐藏告警
调用push添加新告警时,你先执行hide()将当前第一个告警的display设为false,再把新告警推到数组末尾。此时current计算属性返回的仍是数组第一个元素(已隐藏的旧告警),Snackbar的open属性为false,自然无法显示新告警。
具体修复方案
1. 修复Mobx响应式初始化
修改AlertsStore,添加构造函数并完成响应式初始化:
import {just, Maybe, nothing} from 'maybeasy'; import {action, computed, observable, makeObservable} from 'mobx'; import {Alert} from "../base/BaseAlert"; class AlertsStore { @observable alerts: Alert[] = []; constructor() { // 关键:启用装饰器对应的响应式能力 makeObservable(this); } @computed get current(): Maybe<Alert> { return this.alerts.length === 0 ? nothing() : just(this.alerts[0]); } @action hide = () => { if (this.alerts.length > 0) { this.alerts[0].display = false; } }; @action process = () => { this.alerts = this.alerts.slice(1); }; @action push = (alert: Alert) => { // 调整逻辑:先移除旧告警,再添加新告警 this.alerts = [{...alert, display: true}]; }; } const alertsStore = new AlertsStore(); export default alertsStore;
2. 优化Snackbar的关闭逻辑(可选,用于队列式告警场景)
如果需要实现“依次显示多个告警”的队列逻辑,可调整Snackbar的关闭回调,确保隐藏后自动移除旧告警,让下一个告警成为当前显示项:
@observer export class Alerts extends React.Component { render() { return alertsStore.current.cata({ Just: alert => ( <Snackbar anchorOrigin={{vertical: 'top', horizontal: 'right'}} open={alert.display} onClose={() => { alertsStore.hide(); // 延迟执行process,确保Snackbar动画完成后再移除旧告警 setTimeout(() => alertsStore.process(), 300); }} message={alert.message} autoHideDuration={1000} /> ), Nothing: () => <></>, }); } }
同时修改push方法,保留队列逻辑:
@action push = (alert: Alert) => { // 如果当前有正在显示的告警,先隐藏并移除 if (this.alerts.length > 0) { this.hide(); this.process(); } this.alerts.push({...alert, display: true}); };
3. 确保Alert对象属性可观察(可选)
如果需要单独追踪Alert对象内部属性(如display)的变化,可将创建Alert的函数改为返回可观察对象:
import {observable} from 'mobx'; export const alert = (message: string, kind: Alert['kind']): Alert => observable({ message, kind, display: true, } as Alert);
验证步骤
- 先完成Mobx响应式初始化的修复,确认告警数组的变化能被Mobx追踪。
- 测试登录错误场景,观察Snackbar是否正常显示。
- 如果需要队列功能,再调整对应的关闭和push逻辑。
内容的提问来源于stack exchange,提问作者Jun
相关产品推荐
相关产品推荐

