Typescript 类作为 React 状态,重新渲染
Posted
技术标签:
【中文标题】Typescript 类作为 React 状态,重新渲染【英文标题】:Typescript class as React state, rerender 【发布时间】:2021-03-25 07:49:45 【问题描述】:我有以下功能组件:
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
状态是具有isPlaying
类型为boolean
的字段的类。它还有一个定义为togglePlay()
的函数,用于切换isPlaying
。
问题是当togglePlay()
被调用时,React 不会重新渲染组件。我明白为什么(因为 SpotifyPlayer 的实例没有改变,所以你不应该直接更新反应状态)。
我无法调用setSpotifyPlayer()
来更新状态,原因有两个:
SpotifyPlayer
的实例负责切换isPlaying
当我使用 js 解构更改状态时,我丢失了 spotifyPlayer
状态的原型,并且该功能将不再可用。
我想不通。
【问题讨论】:
【参考方案1】:您对问题的理解是正确的。您不能依赖对 SpotifyPlayer
对象内部状态的更改来触发重新渲染。我建议使用本地状态来存储 isPlaying
的值并根据对该值的更改更新 SpotifyPlayer
。
如果播放器对象有某种onChange
监听器,那么我会使用播放器来设置本地状态,而不是相反。
我不确定播放器来自哪个包,所以我假设这个界面:
class SpotifyPlayer
isPlaying: boolean = false;
play(): void
this.isPlaying = true;
pause(): void
this.isPlaying = false;
我们可以使用useRef
来存储对播放器对象的一致引用。
const spotifyPlayer = React.useRef<SpotifyPlayer>(new SpotifyPlayer()).current;
我们会将isPlaying
的值存储在本地状态中。我们可以从玩家那里得到初始值。
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
是唯一会更改值的函数,那么我们可以处理该函数中的更改。
const togglePlay = () =>
if (isPlaying )
spotifyPlayer.pause();
setIsPlaying(false);
else
spotifyPlayer.play();
setIsPlaying(true);
【讨论】:
以上是关于Typescript 类作为 React 状态,重新渲染的主要内容,如果未能解决你的问题,请参考以下文章
我想在辅助函数中操作 React 类组件中存在的状态。我想在 Typescript 中实现相同的目标
Typescript React 空函数作为 defaultProps