react useRef 避坑(在Carousel中使用)

484 阅读1分钟

在map中使用useRef,或在Carousel中,无法定位dom 在轮播中控制多个视频。使用useRef时,map多个useRef处理。

基础使用useRef

// 暂停视频播放
const handleStop = () => {
    showVidref.current.pause();
};

const showVidref = useRef(null);
const ShowVideo = (prop) => (
    <video
      controls
      ref={showVidref}
      style={{
        width: "200px",
      }}
    >
      <source src={prop.url} />
      <track kind="captions" />
    </video>
);

<ShowVideo url="http://abc.mp4" />
<Button onClick={() => handleStop()}>stop</Button>

map+useRef

image.png

问题: 在map中使用useRef情况时。useRef 返回的是一个mutable ref object 。map 以后 current 就指向最后一个dom。所以不能像基础使用时直接取current值。

解决方法:current 对象标记

方法1:

  const showVidref = useRef({});
  const ShowVideo = (prop) => (
    <video
      controls
      ref={(r) => {
        showVidref.current[prop.index] = r;
      }}
      style={{
        width: "200px",
      }}
    >
      <source src={prop.url} />
      <track kind="captions" />
    </video>
  );

  const handleStop = () => {
    showVidref.current[0].pause();
    showVidref.current[1].pause();
  };
  
<div>
    {playList.map((row, index) => (
      <div key={index}>
          <ShowVideo url={row.url} index={index} />
      </div>
    ))}
</div>

方法2 自定义hook useRefMap

处理map + useRef (原理同方法一) www.npmjs.com/package/use…

Carousel 轮播中map useRef

此处要注意在轮播中,为了实现滑动动画效果,antd多复制了一份dom。导致hook useRefMap 使用时,current对象指向了多复制出来一份的dom。

// 同上
// 因为要自带动画特效的原因,antd会自动多复制出一份dom结构。ref current会定位到后面自动多复制的dom。导致stop失效。
// 设置effect 为fade, 不会复制多一份dom 
// 保持滑动效果,可放弃使用useRef,通过刷新组件实现停播video
  const props = {
    effect: "fade",
  };
<Carousel {...props}>
    {playList.map((row, index) => (
      <div key={index}>
         <ShowVideo url={row.url} index={index} />
      </div>
    ))}
</Carousel>