簡體   English   中英

Typescript class 作為反應 state,重新渲染

[英]Typescript class as React state, rerender

我有以下 function 組件:

const Player = () => {
  const [spotifyPlayer, setSpotifyPlayer] = React.useState<SpotifyPlayer | null>(null);

  return (
    <SongControls togglePlay={togglePlay} isPlaying={spotifyPlayer.isPlaying} />
  );
};

SongControls組件負責顯示正確的控制按鈕(開始/暫停):

const SongControls: React.FC<Props> = ({ isPlaying }: Props) => {
  return (
    {isPlaying ? (
      <Pause style={iconBig} onClick={togglePlay} />
    ) : (
      <PlayArrow style={iconBig} onClick={togglePlay} />
    )}
  );
};

Player組件中的spotifyPlayer state 是一個 class ,其字段isPlaying的類型為boolean 它還有一個 function 定義的togglePlay()來切換isPlaying

問題是,當togglePlay()時,React 不會重新渲染組件。 我明白為什么(因為 SpotifyPlayer 的實例沒有改變,這就是為什么你不應該直接更新 react state)。

由於兩個原因,我無法調用setSpotifyPlayer()來更新 state:

  • SpotifyPlayer的實例負責切換isPlaying
  • 當我更改 state 使用 js 解構時,我丟失了spotifyPlayer state 的原型,並且 function 將不再可用。

我無法弄清楚這一點。

你對問題的理解是正確的。 您不能依賴SpotifyPlayer object 的內部 state 的更改來觸發重新渲染。 我建議使用本地 state 來存儲isPlaying的值並根據對該值的更改更新SpotifyPlayer

如果播放器 object 有某種onChange監聽器,那么我將使用播放器設置本地 state 而不是相反。

我不確定播放器來自什么 package,所以我假設這個界面:

class SpotifyPlayer {
  isPlaying: boolean = false;
  play(): void {
    this.isPlaying = true;
  }
  pause(): void {
    this.isPlaying = false;
  }
}

我們可以使用useRef來存儲對播放器 object 的一致引用。

const spotifyPlayer = React.useRef<SpotifyPlayer>(new SpotifyPlayer()).current;

我們將isPlaying的值存儲在本地 state 中。 我們可以從玩家那里得到初始值。

const [isPlaying, setIsPlaying] = React.useState(spotifyPlayer.isPlaying);

為了使isPlaying與播放器保持同步,我們可以使用useEffect

const togglePlay = () => setIsPlaying(!isPlaying);

React.useEffect(() => {
  if ( isPlaying && ! spotifyPlayer.isPlaying ) {
    spotifyPlayer.play();
  } else if ( ! isPlaying && spotifyPlayer.isPlaying ) {
    spotifyPlayer.pause();
  }
}, [spotifyPlayer, isPlaying]);

但是如果togglePlay是唯一會改變值的 function,那么我們可以處理 function 中的變化。

const togglePlay = () => {
   if (isPlaying ) {
       spotifyPlayer.pause();
       setIsPlaying(false);
   } else {
      spotifyPlayer.play();
      setIsPlaying(true);
   }
}

暫無
暫無

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

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