首页 > 解决方案 > React - 通过 useContext 共享变量,以更新和重新渲染组件,但不起作用

问题描述

我正在创建一个练习应用程序(使用 MERN 堆栈和 graphql),它从用户那里获取关键字并获取与这些关键字匹配的 youtube 视频。

获取 youtube 数据后,我将该练习保存在我的 mongoDB 数据库中,并将它们保存在一个数组exerciseArr中。这exerciseArr是通过不同的 React 组件共享的,通过 useContext。

获取请求和接收数据发生在我的ExerciseForm组件中。

我正在使用ExerciseList组件来渲染那些获取的练习(保存在exerciseArr),只要有更新exerciseArr,它应该将项目重新渲染exerciseArrExerciseVideo. 这发生在useEffect组件ExerciseList中。

    useEffect(() => {
        console.log('exerciseArr in ExerciseList', exerciseArr)

        const fetchedExercises = exerciseArr.map( exercise => ( 
            <ExerciseVideo key={exercise._id} 
                id={exercise._id} 
                bodysection={exercise.bodysection}
                duration={exercise.duration}
                title={exercise.title} 
                videoUrl={exercise.videoUrl} 
                favorite={exercise.favorite}/>))
        
        setVideoElements(fetchedExercises)

    }, [exerciseArr])

现在的问题是该ExerciseList组件仅使用来自 的第一个请求进行ExerciseForm渲染,并且它不会重新渲染,除非您使用已渲染的视频元素(即ExerciseList组件的 prat)启动某些操作(单击事件等)。

我的理解是,每次更新exerciseArr,在 ExerciseList 中的 useEffect 都会重新渲染。但这不是发生了吗?

要强制重新渲染组件,我需要使用作为组件一部分的ExrciseList现有元素启动单击事件或任何类型。ExerciseVideoExerciseList

这就是我渲染ExerciseList组件的方式App

....
function App() {
  const { isAuth, exerciseArr } = useContext(Context)
  const hasExercise = exerciseArr.length > 0
  // const authenticatedView = <><ExerciseForm/></> 

  return (
    <div className="App">
      <Switch>
          <Route exact path="/">
              <NavBar />
              <Manual />
              { isAuth ? <ExerciseForm/> : <Login/> }
              { isAuth && hasExercise ? <ExerciseList /> : ''}
          </Route>
....
    

我想知道我是否没有在ExerciseList组件中正确使用 useEffect 以重新渲染自身。或者我如何渲染ExerciseList组件App需要改变。

有人可以帮我解决这个问题吗?

标签: reactjsmernuse-effect

解决方案


我发现了导致问题的错误。

useEffect函数是正确的,但if它应该呈现和更新的语句exerciseArr返回 false。

            if(resData.data.exercises.__typename === 'ExerciseData') {
                //then save those results in exerciseArr
                const graphqlResponse = resData.data.exercises.exercises
                return setExerciseArr(graphqlResponse)
            }

这个块的resData.data.exercises.__typename路径以前不正确。因此根本不更新exerciseArr

*旁注,我将这个useEffect功能移入Context并仅渲染exerciseArrExerciseList创建视频div元素,以使组件更简单。


推荐阅读