0

我有一个 React 功能组件,它以与 Instagram 故事非常相似的方式呈现课程视频播放器。课程中的一些视频(“剪辑”)具有“交互”,会弹出一张卡片,用户可以在其中回答多项选择题。代码简化如下。

在随机课程中,一些交互没有显示出来。在日志交互 1中,它们照常显示(记录了一堆未定义的值,然后在几次重新渲染后记录了数组),但是当调用onClipEnding函数时,交互 2再次未定义。

关于可能发生的事情的任何线索?我最好的猜测是一个陈旧的关闭,但我找不到解决它的方法。

export function getInteractions(lesson_id: string, profile_id?: string) {
  const { data, error } = useSWR<ManyResponse<Interaction>>(
    `${apiRoutes.interactions}/${lesson_id}?per_page=50${
      profile_id ? `&profile_id=${profile_id}` : ''
    }`,
    request,
  )

  return {
    interactions: data && data.data,
    isLoading: !data && !error,
    error,
  }
}

export default function LessonPlayer({ videoIds }) {
  const setVideos = useStoreActions((actions: Actions<Store>) => actions.setVideos)
  const { interactions } = getInteractions(lessonId, currentProfileId)
  console.log('interactions 1', interactions)

  useEffect(() => {
    if (!videoIds && videos) {
      setVideos(videos)
    }
  }, [videoIds, setVideos])

  return (
    <>
      <div>
        {(videoIds || []).map((videoId) => (
          <Video key={videoId} videoId={videoId} onEnd={onClipEnding} />
        ))}
      </div>
      {interactions && (
        <div className="absolute bottom-0 w-full">
          <InteractionCard interaction={interaction} handleInteraction={handleInteraction} />
        </div>
      )}
    </>
  )

  function onClipEnding(videoId: string) {
    const clipInteraction = interactions && interactions.find((item) => item.clip_id == videoId)
    console.log('interactions 2', interactions)
    if (clipInteraction) {
      setInteraction(clipInteraction)
    } else {
      nextClip({ profile_id: currentProfileId, status: 'completed' })
    }
  }

4

1 回答 1

2

onClipEnding这是在初始渲染时创建的陈旧闭包,它捕获interactionsvalue 的变量undefined,然后作为回调传递给<Video />它的onEndprop。在那里,它在初始渲染时保留为陈旧版本,并且在调用之前从未更新。

由于您知道过时的关闭问题,我相信以上信息应该足以让您调试。我会把剩下的留给你。

奖励:我与您分享我的秘密武器,解决陈旧关闭问题的灵丹妙药。进入useFn自定义钩子:

function useFn(fn) {
  const ref = useRef(fn);
  ref.current = fn;

  function wrapper() {
    return ref.current.apply(this, arguments)
  }

  return useRef(wrapper).current
}
于 2021-04-26T16:53:55.187 回答