Redux和use对页面重载的影响

m3eecexj  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(98)

我有react应用程序,我使用redux来管理状态。

假设会发生什么:

Redux持有一个包含_id字符串的对象,在页面上我有一个useEffect,它首先检查_id是否为空字符串,然后调用异步函数onPlantTimelineMount()使用_id获取数据。当用户重新加载页面时,Redux状态默认为loaded,其中_id是一个空字符串,因此调用useEffect中的if语句,使用不同的异步函数ifUserRefreshPage()获取该项,将该项调度到Redux状态,并且仅在调用onPlantTimelineMount()之后。

问题:

ifUserRefreshPage()成功获取数据并将其分配到Redux状态,但onPlantTimelineMount()仍然使用ifUserRefreshPage()调用之前的状态-这意味着_id仍然是空字符串。

值得一提:

ifUserRefreshPage()中,我序列化获取的项(第38行),将其调度到Redux(第39行),console.log获取的项(图像中的第40行),并console.log Redux状态下的项(第41行),它仍然是空的!!怎么样?
x1c 0d1x的数据

验证码:

const currentPlant = useAppSelector(state => state.plants.currentPlant)
    const plantUpdates = useAppSelector(state => state.plants.currentPlant.updates)
    const reduxPlants = useAppSelector(state => state.plants.plants)
    const location = useLocation();
    const { show: showSnackbar, component: snackBar } = useSnackbar();
    async function ifUserRefreshPage() {
        setIsFetching(true)
        const plantId = location.pathname.split('/')[2];
        try {
            console.log(`ifUserRefreshPage invoked`);
            const plantResponse = await fetchPlantById(plantId, '1')
            const serializedPlant = plantManager.serializePlant(plantResponse.data)  // line 38
            dispatch(setCurrentPlant(serializedPlant))                               // line 39
            console.log(serializedPlant);                                            // line 40
            console.log(currentPlant);                                               // line 41
            const gardenResponse = await fetchMyGarden('1')
            dispatch(addPlants(plantManager.serializeGarden(gardenResponse.data)))
        } catch (err) {
            console.log(`error while running ifUserRefreshPage function` + err);
            showSnackbar("Failed to load Timeline", "error");
        } finally {
            setIsFetching(false)
        }
    }

    async function onPlantTimelineMount() {
        setIsFetching(true)
        console.log(`ifUserRefreshPage invoked`);
        try {
            const response = await fetchPlantUpdates(currentPlant._id!)
            if (response.success) {
                dispatch(setUpdatesToCurrentPlant(plantUpdateManager.serializeUpdatesArray(response.data)))
            }
        } catch (err) {
            showSnackbar("Failed to load Timeline", "error");
        } finally {
            setIsFetching(false)
        }
    }
    
    useEffect(() => {
        async function start() {
            if (!currentPlant._id) {
                await ifUserRefreshPage()
            }
           await onPlantTimelineMount()
        }
        start()
    },[])

字符串

wbgh16ku

wbgh16ku1#

我console.log项目在Redux状态(第41行),它仍然是空的!!怎么样?
因为这是一个局部常数。它永远不会改变。这类似于更新状态不会更改局部变量的常见问题。Stack overflow on this topic,React docs on this topic
当你分派你的动作时,你更新了redux商店。这个更新的状态可以通过调用store.getState()来访问,尽管这通常不是你在react应用中直接做的事情。您已经调用了const currentPlant = useAppSelector(state => state.plants.currentPlant),它订阅了存储,因此状态的更改会导致组件重新呈现。当重新渲染发生时,将使用新值创建一个新的本地常量,但您在上一次渲染中的代码无法访问此常量。你的console.log(currentPlant);从以前的渲染将永远只注销旧的值。
由于您在不同的变量中确实有新值,因此我建议您使用它。例如,修改ifUserRefreshPage以返回新工厂:

async function ifUserRefreshPage() {
  setIsFetching(true);
  const plantId = location.pathname.split("/")[2];
  try {
    console.log(`ifUserRefreshPage invoked`);
    const plantResponse = await fetchPlantById(plantId, "1");
    const serializedPlant = plantManager.serializePlant(plantResponse.data);
    dispatch(setCurrentPlant(serializedPlant));
    const gardenResponse = await fetchMyGarden("1");
    dispatch(addPlants(plantManager.serializeGarden(gardenResponse.data)));
    return serializedPlant; // <--------------Added return
  } catch (err) {
    console.log(`error while running ifUserRefreshPage function` + err);
    showSnackbar("Failed to load Timeline", "error");
  } finally {
    setIsFetching(false);
  }
}

字符串
然后修改onPlantTimelineMount,这样你就可以传入工厂:

//              Added argument -----VVVVV
async function onPlantTimelineMount(plant) {
  setIsFetching(true);
  console.log(`ifUserRefreshPage invoked`);
  try {
    const response = await fetchPlantUpdates(plant._id!);
    if (response.success) {
      dispatch(
        setUpdatesToCurrentPlant(
          plantUpdateManager.serializeUpdatesArray(response.data),
        ),
      );
    }
  } catch (err) {
    showSnackbar("Failed to load Timeline", "error");
  } finally {
    setIsFetching(false);
  }
}


并更新您的效果以连接两者:

useEffect(() => {
  async function start() {
    let plant = currentPlant;
    if (!plant._id) {
      plant = await ifUserRefreshPage();
    }
    await onPlantTimelineMount(plant);
  }
  start();
}, []);

相关问题