关于react.js:重复渲染性问题

6次阅读

共计 1876 个字符,预计需要花费 5 分钟才能阅读完成。

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