React 实现keep-alive效果

762 阅读1分钟

前言

vue 中可以使用 keep-alive 组件去缓存组件,切换到其他页面不会销毁被缓存的组件

而在 react 中则没有这种设计

思路

react 中提供了createPortalApi

我们可以吧组件放在自定义的一个容器中,当需要展示的时候拿出来展示

定义一个容器用来将 children 存储到该容器,该容器会在 activetrue 的时候将组件添加到containerRef

当为 false 会将其在 DOM 结构中 remove

代码

import React, { useRef, useLayoutEffect } from "react"
import ReactDOM from 'react-dom';

type IProps = {
  active: boolean;
  children: React.ReactNode;
}

const Conditional: React.FC<IProps> = props => {
  const {current: targetElement} = useRef(document.createElement('div'))
  const containerRef = useRef<HTMLDivElement>(null);
  const activateRef = useRef(false); // 用来判断当前组件是否需要被缓存

  // 如果当前这个组件已经被缓存了 那就返回true 如果没缓存,可能是因为没被加载,返回false不缓存此组件
  activateRef.current = activateRef.current || props.active

  useLayoutEffect(() => {
    if (!containerRef.current) {
      return
    }

    if (props.active) {
      containerRef.current.appendChild(targetElement)
    } else {
      try {
        containerRef.current.removeChild(targetElement)
      } catch (e) { }
    }
  }, [props.active])

  return (
    <>
      <div ref={containerRef} />
      {activateRef.current && ReactDOM.createPortal(props.children, targetElement)}
    </>
  )
}

export default Conditional

使用

<Conditional active>
    <div /> {/* 被缓存的组件 */}
</Conditional>