首页 > 解决方案 > React 不会呈现它收到的最后一个钩子更新

问题描述

我有一个小钩子可以确定连接性,但是当它从falseto更新时true,它似乎永远不会在它变回false. 即日志显示:

Has stopped growing: false
Is connected: false
OFFLINESERVER: false
--------------------------
Has stopped growing: false
Is connected: true
OFFLINESERVER: true
--------------------------
Has stopped growing: false
Is connected: true
OFFLINESERVER: true
--------------------------
Has stopped growing: true
Is connected: true
OFFLINESERVER: false
--------------------------

但 UI 显示之前的值,即

在此处输入图像描述

如果我在日志中添加一个简单的计数,我可以看到最后记录的值是4但 UI 显示3,这意味着最后收到的值没有被呈现。

我把它缩小到这段代码:

应用程序.tsx

import * as React from 'react';
import { Text, View } from 'react-native';
import { useConnectionMonitor } from '../../src';

export default function App() {
  const source = 'https://www.w3.org/TR/PNG/iso_8859-1.txt';
  const offlineHlsServer = useConnectionMonitor(source);

  console.log(`OFFLINESERVER: ${offlineHlsServer}`);
  console.log(`--------------------------`);
  return (
    <View>
      <Text>{`Offline server is live: ${offlineHlsServer}`}</Text>
    </View>
  );
}

连接监视器.ts

import { useEffect, useState } from 'react';
import usePrevious from './utils/usePrevious';

export const useConnectionMonitor = (source: string): boolean => {
  const [isConnected, setIsConnected] = useState<boolean>(false);
  const [manifestLength, setManifestLength] = useState<number | null>(null);
  const previousManifestLength = usePrevious<number | null>(manifestLength);

  useEffect(() => {
    const intervalId = setInterval(async () => {
      const response = await fetch(source, {
        method: 'HEAD',
      });

      setIsConnected(response.ok);

      const length = response.headers.get('Content-Length');
      if (length) {
        setManifestLength(parseInt(length, 10));
      }
    }, 2000);

    return function cleanup() {
      clearInterval(intervalId);
    };
  }, [source]);

  const hasStoppedGrowing = manifestLength !== null && manifestLength === previousManifestLength;
  console.log(`Has stopped growing: ${hasStoppedGrowing}`);
  console.log(`Is connected: ${isConnected}`);
  return isConnected && !hasStoppedGrowing;
};

综上所述:console.log()App.tsx 函数内部清楚地表明最后收到的值是false. 为什么 UI 继续显示之前的值?

标签: javascriptreactjsreact-nativereact-hooks

解决方案


我认为这是因为在您的效果中,当您调用 时setIsConnected,它会触发重新渲染(因为您正在更改状态)。但是,如果唯一改变的是hasStoppedGrowing(就像在最后一个控制台日志中一样),那么它不会触发重新渲染,因为这不是组件状态的一部分。

您可以更改它,以便将结果设置为效果isConnected && !hasStoppedGrowing内的状态。就像是:

const [offlineHlsServer, setOfflineHlsServer] = useState<boolean>(false);

...

setOfflineHlsServer(isConnected && !hasStoppedGrowing);
return offlineHlsServer;

推荐阅读