Reactjs 如何使用React.memo优化性能
我用React前端下了一盘棋。最初,任何移动似乎都是瞬间实现的,但在添加了额外的功能后,例如更改标题的背景以反映轮到谁(白色或黑色背景取决于其白色的移动)和其他类似功能,我的应用程序明显变慢了。我怀疑是这些类型的if语句-Reactjs 如何使用React.memo优化性能,reactjs,react-hooks,Reactjs,React Hooks,我用React前端下了一盘棋。最初,任何移动似乎都是瞬间实现的,但在添加了额外的功能后,例如更改标题的背景以反映轮到谁(白色或黑色背景取决于其白色的移动)和其他类似功能,我的应用程序明显变慢了。我怀疑是这些类型的if语句- const Details = props => { console.log(props.status); let [backGround, setBackGround] = useState("w details") con
const Details = props => {
console.log(props.status);
let [backGround, setBackGround] = useState("w details")
const history = useHistory();
if (props.status.white && backGround === "bl details"){
setBackGround("w details")
} else if (!props.status.white && backGround === "w details"){
setBackGround("bl details")
}
这是因为打印道具的console.log每次移动将打印其语句8次(最初是两次)
我使用的是功能组件而不是类,我对优化的研究使我找到了以下解决方案-
所有这些都指向了React.memo的简单例子,但我显然遗漏了一些东西,因为当我试图实现它时,我得到的只是大量未定义的“道具”错误(我每次使用道具都有一个,这是非常多的)
详细信息。jsx
import React, { useState } from 'react';
import "../App.css"
import DataService from '../service/DataService';
import { useHistory } from 'react-router-dom';
let [backGround, setBackGround] = useState("w details")
const Details = React.memo(props => {if (props.status.white){setBackGround("w details")} else {setBackGround("bl details")}}, (prevProps, props) => prevProps.white === props.white); {
console.log(props.status);
const history = useHistory();
const undo = () => {
DataService.undo()
.then(res => {
console.log(res);
props.setTheBoard(res.data);
props.changeTurn();
})
.catch(err => {
console.log(err);
window.alert(err.response.data.errMessage)
})
}
const restart = () => {
DataService.restartGame()
.then(res => {
console.log(res);
props.setTheBoard(res.data);
props.changeTurn(true);
})
.catch(err => {
console.log(err);
window.alert(err.response.data.errMessage)
})
}
const newGame = () => {
history.push('/');
}
return (
<div className={backGround} >
{props.status.active ? <h2>It is {props.status.playerName}'s turn</h2> :
<div>
<h1 className="check">Game Over!</h1>
<button className="tooltip" onClick={restart}>RESTART<span className="tooltiptext">Play another game vs the same opponent</span></button>
<button className="tooltip" onClick={newGame}>NEW GAME<span className="tooltiptext">Play a game vs a different opponent</span></button>
</div>}
{props.status.active &&
<div>
{props.isMove ? <button className="detailButtons" onClick={props.specialMove}>Special Move</button> : <button className="detailButtons" onClick={() => props.endTheGame(true)}>Forfeit</button> }
{props.isMove ? <button className="detailButtons" onClick={props.unselect}>Unselect Piece</button> : <button className="detailButtons" onClick={() => props.endTheGame(false)}>Draw</button> }
{props.isMove ? <button className="detailButtons">Toggle Sidebar</button> : props.undo && <button className="detailButtons" onClick={() => undo()}>Undo</button> }
{props.status.check && <h1 className="check">You must move out of check!</h1>}
</div> }
</div>
);
}
export default Details;
import React,{useState}来自“React”;
导入“./App.css”
从“../service/DataService”导入数据服务;
从'react router dom'导入{useHistory};
let[背景,挫折]=useState(“w细节”)
const Details=React.memo(props=>{if(props.status.white){setBackGround(“w Details”)}else{setBackGround(“bl Details”)},(prevProps,props)=>prevProps.white==props.white);{
控制台日志(道具状态);
const history=useHistory();
常量撤消=()=>{
DataService.undo()
。然后(res=>{
控制台日志(res);
道具设置板(res.data);
props.changeTurn();
})
.catch(错误=>{
控制台日志(err);
window.alert(err.response.data.errMessage)
})
}
常量重新启动=()=>{
DataService.restartGame()
。然后(res=>{
控制台日志(res);
道具设置板(res.data);
道具。改变方向(真);
})
.catch(错误=>{
控制台日志(err);
window.alert(err.response.data.errMessage)
})
}
const newGame=()=>{
历史推送(“/”);
}
报税表(
{props.status.active?轮到{props.status.playerName}了:
游戏结束!
重新开始与同一对手进行另一场比赛
新游戏对不同对手的游戏
}
{props.status.active&&
{props.isMove?特殊移动:props.endTheGame(true)}>放弃}
{props.isMove?取消选择棋子:props.endTheGame(false)}>平局}
{props.isMove?切换侧栏:props.undo&&undo()}>undo}
{props.status.check&&您必须退出检查!}
}
);
}
导出默认详细信息;
由于此组件中的道具仅在回合更改时更改(props.status.white),因此我认为这将是一个减少不必要的重新渲染的好地方,但我看到的所有解决方案都非常简单。当像这样的道具被广泛使用时,是否可以使用React.memo
如何在保持对道具的访问的同时优化性能?首先,关于在前端测试性能,您必须记住一点 当您在devtools中检查性能、活动时,决不会让devtools保持打开状态,这会大大降低应用程序的性能 其次,
useMemo
和useCallback
都不会给您带来任何性能改进,如果您没有完全渲染,渲染之前可能渲染过的道具,最重要的是,如果您没有在自定义组件中渲染其他自定义组件,那么您可能也不需要使用这些挂钩
那么,我们应该在哪种情况下使用useCallback
和usemo
,以提高性能
在回答这个问题之前,您应该知道值类型和引用类型之间的区别
值类型是不可变的,所以您可以安全地分配、修改和使用它,而不必担心所有权和垃圾收集器
JS中的原语文本类型是值类型:
让a=“你好”
设b=a
//从这里开始,b不拥有引用,因为a是一种值类型
设c=新字符串(“Hello”)
设d=c
//现在d拥有c引用,因为c被初始化为String类的实例
这是一个非常简单的示例,说明了如何使用两种不同的方法创建相同的字符串
第一个是使用文本字符串创建字符串。
第二,使用String类的实例
如果我们这样做:
a==b//true
==
将a
的值与b
中的值进行比较
然而,当我们这样做时,会发生一些不同的事情:
c==d//true
这也会返回true
,但是=
在这里的工作方式不同,它不是比较值,而是比较c的参考严格等于d的参考。如果仅使用==
运算符,c
的值严格等于d
的值,我们无法进行比较,因为两者都是字符串的引用类型,我们应该这样比较:
//toString()在本例中同样有效,但valueOf在本例中更具语义
c、 valueOf()==d.valueOf())
想想a
和b
不指向内存中的引用,而是d
引用在c
中创建的相同的引用
现在,考虑到这一点,让我们回到过去