簡體   English   中英

反應鈎子 useState() 的非常奇怪的行為

[英]Really weird behavior of the react hook useState()

我目前正在使用 Swiper 編寫一個用於簡單幻燈片放映的 React 應用程序,一切正常。 我現在試圖通過使用 setActiveSlide 函數顯示當前幻燈片來改進導航。 第一次加載后,它工作正常。 單擊調用 setActiveSlide 的按鈕后,故事對象被設置為 null,這會導致在您第二次單擊“上一個”或“下一個”按鈕時出現錯誤(Uncaught TypeError: Cannot read property 'slideNext' of null)。 為什么調用setActiveSlide后story對象設置為null? 請幫忙

這是應用程序的簡化版本

import React, { useState, useEffect, useRef } from "react";
import Swiper from "swiper";

const Slideshow = props => {
    var swiper = useRef();
    var story = null;
    const [activeSlide, setActiveSlide] = useState("");

    useEffect(() => {
        story = new Swiper(swiper.current, {
            loop: false,
            speed: 1100
        });
    }, []);

    const prevSlide = () => {
        setActiveSlide("PREV");
        story.slidePrev();
    };

    const nextSlide = () => {
        setActiveSlide("NEXT");
        story.slideNext();
    };

    return (
        <div className="container-story" ref={swiper}>
            <div className="container-story-wrapper swiper-wrapper">
                {props.children}
            </div>

            <div className="navigation">
                <button onClick={prevSlide}> Previous </button>
                <button onClick={nextSlide}> Next </button>

                {activeSlide}
            </div>
            <div className="lightbox-container"></div>
        </div>
    );
};
export default Slideshow; 

這是一個函數組件,因此如果您希望一個變量在多次渲染中保持不變,那么您不能像使用var story = null那樣在本地聲明它。 您的第一個渲染將設置它,但是當組件重新渲染時,您將其設置回 null。

處理這個問題的正確方法是使用useRef鈎子。 這是一種讓變量在多次渲染中保持不變的方法。

聲明它: const _story = useRef(null);

要讀取/寫入_story變量,您需要訪問_story.current 所以在你的useEffect掛載中你應該使用這個:

_story.current = new Swiper(swiper.current, {
    loop: false,
    speed: 1100
});

在你的處理程序中: _story.current.slideNext();

您可以在此處閱讀有關useRef更多信息。

所以問題是

每次渲染后,React Hook useEffect 內部對“story”變量的賦值將丟失。 要隨着時間的推移保留該值,請將其存儲在 useRef Hook 中,並將可變值保留在 '.current' 屬性中。 否則,您可以直接在 useEffect 中移動此變量。

所以你需要更新如下

import React, { useState, useEffect, useRef } from "react";
import "./styles.css";

import Swiper from "swiper";

const Slideshow = props => {
  var swiper = useRef();
  var story = useRef(null);
  const [activeSlide, setActiveSlide] = useState("");

  useEffect(() => {
    story.current = new Swiper(swiper.current, {
      loop: false,
      speed: 1100
    });
  }, []);

  const prevSlide = () => {
    setActiveSlide("PREV");
    story.current.slidePrev();
  };

  const nextSlide = () => {
    setActiveSlide("NEXT");
    story.current.slideNext();
  };

  return (
    <div className="container-story" ref={swiper}>
      <div className="container-story-wrapper swiper-wrapper">
        {props.children}
      </div>

      <div className="navigation">
        <button onClick={prevSlide}> Previous </button>
        <button onClick={nextSlide}> Next </button>

        {activeSlide}
      </div>
      <div className="lightbox-container" />
    </div>
  );
};
export default Slideshow;

工作代碼沙盒

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM