我们先来假设一种场景:当进入页面时需要去请求获取初始数据,初始数据中有一个字段A,当A====true时需要弹出一个弹窗。
先封装一个弹窗组件,组件接口两个参数visible、close,visible控制是否显示弹窗,close用来关闭弹窗
import React from 'react';
import styles from './index.module.scss';
interface IProps {
visible: boolean;
close: () => void;
}
const Popup = (props: IProps) => {
const { visible, close } = props;
return (
visible ?
<div className={styles.container}>
<div className={styles.box}>
<p>确定要删除吗?</p>
<div>
<button onClick={close}>取消</button>
<button>确认</button>
</div>
</div>
</div>
:
<></>
)
}
export default Popup;
然后在页面中调用
import { inject, observer } from 'mobx-react';
import React, { useEffect } from 'react';
import Store from '../stores/Store';
import Popup from './Popup';
interface IProps {
store?: Store;
}
const Main = (props: IProps) => {
const { store } = props;
const { visible, setVisible } = store as Store;
// 在dom挂在后執行
useEffect(() => {
setVisible(true) // 模拟请求,弹出弹窗
})
return <div>
<Popup visible={visible} close={() => setVisible(false)}></Popup>
</div>
}
export default inject('store')(observer(Main));
这里使用mobx@1.15.4,mobx-react@6.2.2,mobx6版本写法有变动
import { action, observable } from "mobx";
class Store {
@observable visible = true;
@action
setVisible = (visible: boolean) => {
this.visible = visible;
}
}
export default Store;
当运行项目时,会发现每次点击关闭弹窗,弹窗又立即重新弹出。这是因为点击关闭时store
中的visible
发生变化,导致只要类组件render
方法或者函数组件return
中使用到visible
的组件都会重新渲染,重新渲染又会触发useEffect hooks
发送请求,如此循环,使得出现上述现象。
那么如何解决上述问题呢?
如果能不触发useEffect hooks
是不是可以解决呢?不在外部传入visible以及close,而是在popup组件内部依赖store获取visible和close,这样父组件Main就不用重新渲染,进而useEffect hooks
也不用再次执行。
将popup组件实现方式改成如下:
import React from 'react';
import { inject, observer } from 'mobx-react';
import styles from './index.module.scss';
import Store from '../../stores/Store';
interface IProps {
store: Store;
}
const Popup = (props: IProps) => {
const { store } = props;
const { visible, close } = store as Store;
return (
visible ?
<div className={styles.container}>
<div className={styles.box}>
<p>确定要删除吗?</p>
<div>
<button onClick={close}>取消</button>
<button>确认</button>
</div>
</div>
</div>
:
<></>
)
}
export default inject('store')(observer(Popup));
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。