咱们先来假如一种场景:当进入页面时须要去申请获取初始数据,初始数据中有一个字段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));