React TypeScript:useState永不更新

时间:2019-11-15 08:56:18

标签: reactjs typescript

我不明白为什么state.startSlide永远不会更新为1,2,3或4,始终为0

import React, { useState, useEffect } from "react";
import image1 from "../images/carousel/screen-1.png";
import image2 from "../images/carousel/screen-2.png";
import image3 from "../images/carousel/screen-3.png";
import image4 from "../images/carousel/screen-4.png";
import image5 from "../images/carousel/screen-5.png";

const Carousel: React.FC = () => {
  interface StateInterface {
    showImage: any;
    startSlide: number;
  }

  const [state, setState] = useState<StateInterface>({
    showImage: image1,
    startSlide: 0
  });

  useEffect(() => {
    const images = [image1, image2, image3, image4, image5];
    if (state.startSlide === 0) {
      setInterval(function() {
        let currentIndex = state.startSlide;
        console.log(state.startSlide) // <== always logs 0 
        console.log(currentIndex) // <== always logs 0 
        if (state.startSlide < 5) currentIndex++;
        else currentIndex = 1;
        console.log(state.startSlide) // <== always logs 0
        console.log(currentIndex) // <== always logs 1
        setState({
          showImage: images[currentIndex],
          startSlide: currentIndex,
        });
        console.log(state.startSlide) // <== always logs 0 
        console.log(currentIndex) // <== always logs 1
      }, 3000);
    }
  }, [state, setState]);

  return (
    <div className="carousel">
      <p>{state.startSlide}</p> // <== Shows 0 then shows 1 but never 2,3,4
      <img src={state.showImage}></img>
    </div>
  );
};

export { Carousel };

3 个答案:

答案 0 :(得分:1)

您的代码存在问题,是您尝试直接更改状态:state.startSlide。但是,永远不要直接更改状态,请始终调用set函数。直接改变状态会导致奇怪的错误,以及难以优化的组件。这是您应该做的:

import React, { useState, useEffect } from "react";
import image1 from "../images/carousel/screen-1.png";
import image2 from "../images/carousel/screen-2.png";
import image3 from "../images/carousel/screen-3.png";
import image4 from "../images/carousel/screen-4.png";
import image5 from "../images/carousel/screen-5.png";

const Carousel: React.FC = () => {
  const [showImage, setShowImage] = useState('')
  const [startSlide, setStartSlide] = useState(0)

  useEffect(() => {
    const images = [image1, image2, image3, image4, image5];
    if (startSlide === 0) {
      setInterval(function () {
        console.log(startSlide)
        if (startSlide < 5) {
          setStartSlide(startSlide => startSlide++)
        }
        else setStartSlide(1)
        setShowImage(images[startSlide])
        console.log(startSlide)
      }, 3000);
    }
  }, [startSlide]);

  return (
    <div className="carousel">
      <p>{startSlide}</p>
      <img src={showImage}></img>
    </div>
  );
};

export { Carousel };

答案 1 :(得分:0)

您必须删除if (state.startSlide === 0) {},并在startSlide处增加< 4

工作演示:

const { useState, useEffect } = React;
const images = ['image1', 'image2', 'image3', 'image4', 'image5'];

const Carousel: React.FC = () => {

  const [state, setState] = useState({
    showImage: 'image1',
    startSlide: 0
  });

  useEffect(() => {
    
    const interval = setInterval(function() {
        setState(({ startSlide: prevStartSlide }) => {
          console.log(prevStartSlide);
          let currentIndex = prevStartSlide;
          if (currentIndex < 4) currentIndex++;
          else currentIndex = 0;
          return { showImage: images[currentIndex],
          startSlide: currentIndex };
        });
   }, 3000);
    
    return () => clearInterval(interval);
  }, []);

  return (
    <div className="carousel">
      <p>{state.startSlide}</p>
      {state.showImage}
    </div>
  );
};

ReactDOM.render(<Carousel />, document.getElementsByTagName('body')[0]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>

但是请注意,这并不是最好的方法,更多信息:Making setInterval Declarative with React Hooks

答案 2 :(得分:-1)

我认为您可以在这种情况下使用setInterval,这是一小段代码,可以帮助您实现这一目标。

如果您需要更多帮助,请发表评论。

希望它可以解决您的问题

 useEffect(() => {
    const interval = setInterval(() => {
      yourOperations()
    }, 3000);

    return () => clearInterval(interval);
  });