【发布时间】:2021-04-05 20:28:08
【问题描述】:
问题
如果传递给 setCurrentlyPlaying() 的状态不同,我的组件每秒渲染一次,而不是仅渲染一次。如何解决此问题?
背景
我想每 1 秒检查一次 API。除了第一次渲染,我只希望我的组件在incomingSong 与currentPlayingSong 不同时重新渲染。如果传入的状态与基于 Object.is 比较算法的先前状态不同,我依靠 State 钩子仅触发重新渲染的能力。即使我只返回(<div></div>);在我的组件中,它继续每 1 秒渲染一次,因此问题似乎源于此逻辑。我通过在我的 Spotify 上播放 NOTHING 来测试它,所以它总是进入第一个 if 语句并且它仍然每秒重新渲染(打印 console.log("RENDERED") 语句)。
const [currentlyPlayingSong, setCurrentlyPlayingSong] = useState({ type: 'Now Playing', name: 'No Song Playing', artists: [], imageUrl: ''});
console.log("RENDERED")
useEffect(() => {
console.log("initial effect including updateSongs");
const updateSongs = async () => {
const result = await getCurrentlyPlaying();
var incomingSong = {};
// no song is playing
if(result.data === "") {
incomingSong = { type: 'Now Playing', name: 'No Song Playing', artists: [], imageUrl: ''};
}
// some song is playing
else {
var songJSONPath = result.data.item;
incomingSong = {
type: 'Now Playing',
name: songJSONPath.name,
id: songJSONPath.id,
artists: songJSONPath.artists.map(artist => artist.name + " "),
imageUrl: songJSONPath.album.images[songJSONPath.album.images.length - 2].url,
};
}
// console.log("currentlyPlayingSong: ", currentlyPlayingSong)
// console.log("incomingSong: ", incomingSong);
// this line!!!!
setCurrentlyPlayingSong(incomingSong);
}
updateSongs();
const timer = setInterval(updateSongs, 1000);
return () => clearInterval(timer);
},[]);
【问题讨论】:
-
功能组件主体中的控制台日志实际上并不是组件渲染频率的准确度量对于 DOM,您应该在
useEffect挂钩中执行此操作。此外,updateSongs每次调用时都会创建一个新的incomingSong对象引用,并且由于 react 使用浅引用相等,因此每次setCurrentlyPlayingSong(incomingSong);时都会触发重新渲染。您应该在 使用新值更新状态之前手动执行此条件检查。如何确定对象之间的相等性取决于您。id似乎是个不错的选择。 -
@sj123 但是你总是将一个新对象传递给
setCurrentlyPlayingSong所以,React 无法理解它得到了相同的歌曲。
标签: javascript reactjs react-hooks