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