![](/img/trans.png)
[英]React - weird behavior when useState hook sets state for the first time vs subsequent times
[英]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.