redux 如何在useEffect中使用state的最新值?

a64a0gku  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(207)

我的组件每4秒渲染一个图像。当我点击图像时,我想停止渲染新的图像。为此,我使用了useEffect挂钩。当我点击图像时,状态hasToRefresh会改变它的值,但在useEffect中它不会改变。这是我的代码:

import { useEffect, useState } from "react";

const VariableImage = () => {
  const imageUrl = "https://picsum.photos/200";
  const imageRefresh = "?forcerefresh=";

  const [image, setImage] = useState(imageUrl);
  const [hasToRefresh, setHasToRefresh] = useState(true);

  useEffect(() => {
    if (hasToRefresh) {
      setInterval(() => {
        setImage(imageUrl + imageRefresh + Math.random());
      }, 4000);
    }
  }, [imageUrl, imageRefresh, hasToRefresh]);

  return (
    <>
      <img
        src={image}
        onClick={() => setHasToRefresh(!hasToRefresh)}
        alt="scenery"
        height="200"
        width="200"
      />
    </>
  );
};

export default VariableImage;

沙盒中还包括:https://codesandbox.io/s/variable-image-zxhejs
当我点击图片的时候,我该怎么做才能不渲染更多的图片呢?如果有人能帮助我,我将非常感激。谢谢。

izkcnapc

izkcnapc1#

你永远不会停止你的间隔,为了只为hasToRefresh触发useEffect(),我会把图像字符串的创建移到它之外。

const VariableImage = () => {
  const imageUrl = "https://picsum.photos/200";
  const imageRefresh = "?forcerefresh=";
  const [imageNumber, setImageNumber] = useState(Math.random());
  const image = imageUrl + imageRefresh + imageNumber;
  const [hasToRefresh, setHasToRefresh] = useState(true);

  const intervalRef = useRef();

  useEffect(() => {
    if (hasToRefresh) {
      intervalRef.current = setInterval(() => {
        setImageNumber(Math.random());
      }, 1000);
    }
    return () => {
      intervalRef.current && clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
  }, [hasToRefresh]);

  return (
    <>
      <img
        src={image}
        onClick={() => setHasToRefresh(!hasToRefresh)}
        alt="scenery"
        height="200"
        width="200"
      />
    </>
  );
};

以下是更新后的代码和框:https://codesandbox.io/s/variable-image-forked-oxfgc9?file=/src/VariableImage/VariableImage.js:54-896

dphi5xsq

dphi5xsq2#

正如Roy Schut提到的,你永远不会停止你的计时器。但是最好的选择是在图像不应该刷新的时候停止计时器。下面是我喜欢的代码。

import { useEffect, useState, useRef } from "react";

const VariableImage = () => {
  const imageUrl = "https://picsum.photos/200";
  const imageRefresh = "?forcerefresh=";

  const [image, setImage] = useState(imageUrl);
  const [hasToRefresh, setHasToRefresh] = useState(true);
  const intervalRef = useRef(null);

  useEffect(() => {
    startTimer();

    return () => stopTimer();
  }, []);

  const startTimer = () => {
    intervalRef.current = setInterval(() => {
      setImage(imageUrl + imageRefresh + Math.random());
    }, 4000);
  };

  const stopTimer = () => {
    clearInterval(intervalRef.current);
  };

  const toggleRefresh = () => {
    if (hasToRefresh) {
      stopTimer();
    } else {
      startTimer();
    }
    setHasToRefresh(state => !state);
  };

  return (
    <>
      <img
        src={image}
        onClick={() => toggleRefresh()}
        alt="scenery"
        height="200"
        width="200"
      />
    </>
  );
};

export default VariableImage;

相关问题