【发布时间】:2021-12-19 08:55:30
【问题描述】:
为此,我将播放媒体 ID 与列表中的 ID 进行比较,以应用正确的样式。 我的问题是,当单击另一个项目时,所有项目都会重新渲染,因为它们依赖于可观察的播放媒体。
class AppStore {
...
get playingVideo() {
if (!this.player.videoId || this.player.isStopped) {
return null;
}
return this.videos[this.player.videoId];
}
}
const DraggableMediaItem = observer(({ video, index }) => {
const store = useAppStore();
const isMediaActive = computed(
() => store.playingVideo && video.id === store.playingVideo.id
).get();
console.log("RENDER", video.id);
const onMediaClicked = (media) => {
if (!isMediaActive) {
playerAPI.playMedia(media.id).catch(snackBarHandler(store));
return;
}
playerAPI.pauseMedia().catch(snackBarHandler(store));
};
let activeMediaProps = {};
if (isMediaActive) {
activeMediaProps = {
autoFocus: true,
sx: { backgroundColor: "rgba(246,250,254,1)" },
};
}
return (
<Draggable draggableId={video.id} index={index}>
{(provided, snapshot) => (
<ListItem
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={getItemStyle(
snapshot.isDragging,
provided.draggableProps.style
)}
button
disableRipple
{...activeMediaProps}
onClick={() => onMediaClicked(video)}
>
<Stack direction="column" spacing={1} sx={{ width: "100%" }}>
<Stack direction="row" alignItems="center">
<ListItemAvatar>
<MediaAvatar video={video} />
</ListItemAvatar>
<ListItemText primary={video.title} />
<ListItemText
primary={durationToHMS(video.duration)}
sx={{
textAlign: "right",
minWidth: "max-content",
marginLeft: "8px",
}}
/>
</Stack>
</Stack>
</ListItem>
)}
</Draggable>
);
});
我认为将 isMediaActive 设为计算值可以防止这种情况发生,但由于计算值基于更改,因此会触发更新。
是否可以仅在计算值更改时重新渲染?
[编辑]
根据@danila 的评论,我清理了我的代码并注入了isActive 参数。但是,我一定还是遗漏了一些东西,因为当播放器的视频发生变化时,List 不会重新渲染。
那将是当前的伪代码:
const MediaItem = observer(({ isActive }) => {
let activeMediaProps = {};
if (isActive) {
activeMediaProps = {
sx: { backgroundColor: "rgba(246,250,254,1)" },
};
}
return <ListItem {...activeMediaProps}> ... </ListItem>;
});
const Playlist = observer(() => {
const store = useAppStore();
const items = store.playlist;
return (
<List>
{items.map((item) => (
<MediaItem isActive={item.id === store.player.videoId} />
))}
</List>
);
});
[编辑 2]
带有工作示例的代码沙箱链接:
https://codesandbox.io/s/silent-lake-2lvdc?file=/src/App.js
提前感谢您的帮助和时间。
【问题讨论】:
标签: reactjs mobx react-functional-component mobx-react computed-observable