使用 shouldComponentUpdate 每秒重新渲染块组件
Using shouldComponentUpdate for block component re-render every second
那个游戏是用 react 开发的,redux.I 不是 react-redux 开发人员(我是 .net 开发人员),但我必须继续那个项目,所以我是 react 和 redux 的新手
那个游戏性能太差 android phones.So 我分析 project.I 看到组件渲染方法工作每个 second.My 组件每秒包含超过 30 个其他 components.So它会重新渲染,这会导致某些旧 android 手机
性能不佳
为什么 React 组件每秒都重新渲染?我可以阻止它吗?
我搜索那个问题,我看到解决方案是 shouldComponentUpdate function
shouldComponentUpdate(nextProps,nextState) {
console.log(nextProps.gameStore.get('state'));//waiting
console.log(this.props.gameStore.get('state'));//waiting
console.log(this.state);
console.log(nextState);
if (nextProps.gameStore.get('state')==this.props.gameStore.get('state')) {
return false;
}
else {
return true;
}
}
但是在这个函数中 nextstate 和这个 state 是一样的,
nextProps.gameStore.get('state') 和 this.props.gameStore.get('state') 是 same.Why 下一个状态和当前状态相同?我该怎么办?我使用构造函数但是它还是一样这里是我所有的组件代码
import React from 'react';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
//import { default as HTML5Backend } from 'react-dnd-touch-backend';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { bindFirstArguments } from 'utils/bindFirstArgument';
import * as OkeyGameActions from 'actions/OkeyGameActions';
import * as OkeyNetActions from 'actions/OkeyNetActions';
import * as OkeyChatActions from 'actions/Chatactions';
import { SeatDirection } from 'constants/AppConstants';
import { OkeyScoreboardDialog }
from 'components/OkeyScoreboardDialog/OkeyScoreboardDialog';
import OkeyMatchResultDialog
from 'components/OkeyMatchResultDialog/OkeyMatchResultDialog';
import OkeyRackWrapper from 'components/OkeyRackWrapper/OkeyRackWrapper';
import OkeyTopToolbar from 'components/OkeyTopToolbar/OkeyTopToolbar';
import OkeyTableToolbar from 'components/OkeyTableToolbar/OkeyTableToolbar';
import OkeyTableCenter from 'components/OkeyTableCenter/OkeyTableCenter';
import CustomDragLayer from 'components/CustomDragLayer/CustomDragLayer';
import MessageList from 'components/chat/MessageList';
import PrivateEastMessageList from 'components/chat/PrivateEastMessageList';
import PrivateNorthMessageList from 'components/chat/PrivateNorthMessageList';
import PrivateWestMessageList from 'components/chat/PrivateWestMessageList';
import PrivateSouthMessageList from 'components/chat/PrivateSouthMessageList';
import './_OkeyGame.scss';
function toJS(item) {
if (item === null) {
return null;
}
//var item1=item.toJS();
//if (item1.color==='BLACK') {
// var a='a';
//}
if (item == undefined) {
return;
}
return item.toJS();
}
function getRelativeDirection(selfSeat, direction) {
let relativeDirection = direction;
if (selfSeat >= 0) {
relativeDirection = (selfSeat - direction + 4) % 4;
}
return relativeDirection;
}
class OkeyGame extends React.Component {
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps,nextState) {
console.log(nextProps.gameStore.get('state'));//waiting
console.log(this.props.gameStore.get('state'));//waiting
console.log(this.state);
console.log(nextState);
if (nextProps.gameStore.get('state')==this.props.gameStore.get('state')) {
return false;
}
else {
return true;
}
}
render() {
const { dispatch, gameStore, gamePlay, playRules } = this.props;
let actions = bindActionCreators(OkeyGameActions, dispatch);
let netActions = bindActionCreators(OkeyNetActions, dispatch);
const currentTurn = gameStore.get('currentTurn');
const playState = {
selectedStone: gamePlay.get('selectedStone'),
gosterge: gamePlay.get('gosterge'),
middleStoneCount: gamePlay.get('middleStoneCount'),
currentTurn: currentTurn
};
if (playState.gosterge != undefined) {
window.localStorage.setItem('gostergeNumber', playState.gosterge._root.entries[0][1]);
window.localStorage.setItem('gostergeColor', playState.gosterge._root.entries[1][1]);
}
const hasOpenedStonesThisTurn = {
hasOpenedSequenceThisTurn: playRules.get('hasOpenedSequenceThisTurn'),
hasOpenedPairsThisTurn: playRules.get('hasOpenedPairsThisTurn')
};
const rules = {
canOpenSequence: playRules.get('canOpenSequence'),
canOpenPairs: playRules.get('canOpenPairs'),
canWithdraw: playRules.get('canWithdraw'),
canDiscard: playRules.get('canDiscard'),
canCollectOpen: playRules.get('canCollectOpen'),
canLeaveTaken: playRules.get('canLeaveTaken'),
canProcessStone: playRules.get('canProcessStone')
};
const discardMiniBoxes = {
discardMiniBoxPairs: gamePlay.get('pairs'),
discardMiniBoxSequence: gamePlay.get('sequence')
};
const selfSeat = gameStore.get('selfSeat');
const { westSeat, eastSeat, northSeat, southSeat } =
{
westSeat: getRelativeDirection(selfSeat, SeatDirection.WEST),
eastSeat: getRelativeDirection(selfSeat, SeatDirection.EAST),
northSeat: getRelativeDirection(selfSeat, SeatDirection.NORTH),
southSeat: getRelativeDirection(selfSeat, SeatDirection.SOUTH)
};
const players = {
selfSeat: selfSeat,
pSouth: {
seatId: southSeat,
discardStones: gamePlay.getIn(['discardStones', southSeat]),
profile: toJS(gameStore.getIn(['players', southSeat])),
dispatch: dispatch
},
pNorth: {
seatId: northSeat,
discardStones: gamePlay.getIn(['discardStones', northSeat]),
profile: toJS(gameStore.getIn(['players', northSeat])),
dispatch: dispatch
},
pEast: {
seatId: eastSeat,
discardStones: gamePlay.getIn(['discardStones', eastSeat]),
profile: toJS(gameStore.getIn(['players', eastSeat])),
dispatch: dispatch
},
pWest: {
seatId: westSeat,
discardStones: gamePlay.getIn(['discardStones', westSeat]),
profile: toJS(gameStore.getIn(['players', westSeat])),
dispatch: dispatch
}
};
let profiles = [
players.pSouth.profile,
players.pEast.profile,
players.pNorth.profile,
players.pWest.profile
];
localStorage.setItem("selfSeat", selfSeat);
localStorage.setItem("roomID", gameStore.get('id'));
if (selfSeat == 0)
profiles = [players.pSouth.profile,players.pEast.profile,players.pNorth.profile,players.pWest.profile];
else if (selfSeat == 1)
profiles = [players.pWest.profile,players.pSouth.profile,players.pEast.profile,players.pNorth.profile];
else if (selfSeat == 2)
profiles = [players.pNorth.profile,players.pWest.profile,players.pSouth.profile,players.pEast.profile];
else if (selfSeat == 3)
profiles = [players.pEast.profile,players.pNorth.profile,players.pWest.profile,players.pSouth.profile];
const matchState = {
name: gameStore.getIn(['options', 'name']),
maxRounds: gameStore.getIn(['options', 'rounds']),
stake: gameStore.getIn(['options', 'stakes']),
round: gameStore.get('round')
};
const owner = gamePlay.get('ownerID');
const scoreboard = gameStore.get('scoreboard');
const matchResult = gameStore.get('matchResult');
const restCountdown = gameStore.get('restCountdown');
const roomState = gameStore.get('roomState');
const { messageList } = this.props;
const { privateEastMessageList } = this.props;
const { privateNorthMessageList } = this.props;
const { privateWestMessageList } = this.props;
const { privateSouthMessageList } = this.props;
let chatActions = bindActionCreators(OkeyChatActions, dispatch);
// const dispatch1 = this.props
// each action has a first argument of room id
netActions = bindFirstArguments(netActions, gameStore.get('id'));
let from = gameStore.get('from');
let to = gameStore.get('to');
let gift = gameStore.get('gift');
let from1 = gameStore.get('from1');
let to1 = gameStore.get('to1');
let gift1 = gameStore.get('gift1');
let from2 = gameStore.get('from2');
let to2 = gameStore.get('to2');
let gift2 = gameStore.get('gift2');
let from3 = gameStore.get('from3');
let to3 = gameStore.get('to3');
let gift3 = gameStore.get('gift3');
let arayan = gameStore.get('arayan');
let aranan = gameStore.get('aranan');
return (
<div className="game-background" style={{background: 'url(http://okey101.xyz/staticImg/background.png)',backgroundSize:'cover'}}>
<div className="okey-game flex-centered-column">
<CustomDragLayer isMini={gamePlay.get('isOver') > 0}></CustomDragLayer>
<MessageList {...chatActions} {...netActions} messageList={messageList} />
<OkeyScoreboardDialog profiles={profiles}
scoreboard={scoreboard} />
<OkeyMatchResultDialog matchResult={matchResult}
{...netActions}
{...actions}
roomState={roomState}/>
<OkeyTopToolbar {...netActions}
{...matchState}
profiles={profiles}/>
<OkeyTableCenter {...actions}
{...netActions}
{...playState}
{...rules}
{...discardMiniBoxes}
{...players}
owner={owner}
messageList={messageList}
privateEastMessageList={privateEastMessageList}
privateNorthMessageList={privateNorthMessageList}
privateWestMessageList={privateWestMessageList}
privateSouthMessageList={privateSouthMessageList}
from={from}
to={to}
gift={gift}
from1={from1}
to1={to1}
gift1={gift1}
from2={from2}
to2={to2}
gift2={gift2}
from3={from3}
to3={to3}
gift3={gift3}
arayan={arayan}
aranan={aranan}
stones={gamePlay.get('stones')}/>
<OkeyRackWrapper {...actions}
{...netActions}
{...playState}
stones={gamePlay.get('stones')}
stoneGroups={gamePlay.get('stoneGroups')}/>
<OkeyTableToolbar {...actions}
{...netActions}
{...rules}
restCountdown={restCountdown}
currentTurn={currentTurn}
{...hasOpenedStonesThisTurn}
roomState={roomState}
stones={gamePlay.get('stones')}
{...discardMiniBoxes}
okeyStone={gamePlay.get('okeyStone')}/>
</div>
</div>
);
}
}
const mapStateToProps = (state => ({
gameStore: state.gameStore,
gamePlay: state.gamePlay,
playRules: state.playRules,
messageList: state.MessageList,
privateEastMessageList: state.PrivateEastMessageList,
privateNorthMessageList: state.PrivateNorthMessageList,
privateWestMessageList: state.PrivateWestMessageList,
privateSouthMessageList: state.PrivateSouthMessageList
}));
const OkeyGameWithDnD = DragDropContext(HTML5Backend)(OkeyGame);
export default connect(mapStateToProps)(OkeyGameWithDnD);
编辑:使用 Aftab Khan 指令,我将组件更改为 PureComponent,但页面打不开,控制台中也没有错误
我改成
const mapStateToProps = (state => ({
gameStore: toJS(state.gameStore),
gamePlay: toJS(state.gamePlay),
playRules: toJS(state.playRules),
messageList: toJS(state.MessageList),
privateEastMessageList: toJS(state.PrivateEastMessageList),
privateNorthMessageList: toJS(state.PrivateNorthMessageList),
privateWestMessageList: toJS(state.PrivateWestMessageList),
privateSouthMessageList: toJS(state.PrivateSouthMessageList)
}));
但还是不行
然后我把它改成这个
const mapStateToProps = (state => ({
gameStore: state.gameStore.toJS(),
gamePlay: state.gamePlay.toJS(),
playRules: state.playRules.toJS(),
messageList: state.MessageList.toJS(),
privateEastMessageList: state.PrivateEastMessageList.toJS(),
privateNorthMessageList: state.PrivateNorthMessageList.toJS(),
privateWestMessageList: state.PrivateWestMessageList.toJS(),
privateSouthMessageList: state.PrivateSouthMessageList.toJS()
}));
但它仍然无法在浏览器中打开
看来你需要 React.PureComponent
。
这是它的link。 Link
基本上它所做的是在渲染每个组件之前,它会检查组件的道具或状态是否有任何变化。如果没有变化,它不会重新渲染。
看起来您在 reducer 中使用了不可变数据结构。在你的 mapStateToProps 中,将所有不可变数据更改为调用 toJS()
方法的普通 JS 对象。然后 PureComponent 将按预期工作。
关于您的组件,我注意到的很少
render
方法对子组件进行大量初始化
shouldComponentUpdate
是不必要的,因为它只处理道具(这是预期的,因为你所有的状态都在 redux 商店中)。
PureComponent 是不必要的,因为您正在使用 connect()
将它连接到商店。您的组件没有状态,它更好地发挥作用 components created using a simple es6 arrow function
对于 2. 和 3. 请参考 note 优化 connect()
为您创建容器。
现在,如果不检查组件的每一行,就不可能告诉您为什么组件每秒都在渲染。但是,仔细考虑以下内容可以帮助您确保仅在必要时节俭地触发重新渲染。
1.保持 render()
方法尽可能轻量级
render
可能是所有组件中调用次数最多的方法。更臃肿的是你渲染周期会很慢。你可以把你 localStorage.setItems
全部移到 componentWillReceiveProps
。这些 synchronous LocalStorage calls 中的每一个都占用了渲染时间。
2。删除 shouldComponentUpdate
。相反,只将那些道具传递给它绝对需要的组件。制作尽可能多的组件无状态纯函数
shouldComponentUpdate 是组件的逃生舱口,组件需要渲染更多道具。 sCU 的缺点:它在每个组件重新渲染之前运行。在某些情况下,它可以减慢速度而不是加快速度。请参阅 jimfb 的评论 here。这支持我将尽可能多的组件转换为无状态功能组件的建议 - 可能包括您在此处发布的组件
3。如果您的组件是无状态的,则不需要 PureComponent javascript 函数只接受它们需要的道具。
那个游戏是用 react 开发的,redux.I 不是 react-redux 开发人员(我是 .net 开发人员),但我必须继续那个项目,所以我是 react 和 redux 的新手 那个游戏性能太差 android phones.So 我分析 project.I 看到组件渲染方法工作每个 second.My 组件每秒包含超过 30 个其他 components.So它会重新渲染,这会导致某些旧 android 手机
性能不佳为什么 React 组件每秒都重新渲染?我可以阻止它吗? 我搜索那个问题,我看到解决方案是 shouldComponentUpdate function
shouldComponentUpdate(nextProps,nextState) {
console.log(nextProps.gameStore.get('state'));//waiting
console.log(this.props.gameStore.get('state'));//waiting
console.log(this.state);
console.log(nextState);
if (nextProps.gameStore.get('state')==this.props.gameStore.get('state')) {
return false;
}
else {
return true;
}
}
但是在这个函数中 nextstate 和这个 state 是一样的, nextProps.gameStore.get('state') 和 this.props.gameStore.get('state') 是 same.Why 下一个状态和当前状态相同?我该怎么办?我使用构造函数但是它还是一样这里是我所有的组件代码
import React from 'react';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
//import { default as HTML5Backend } from 'react-dnd-touch-backend';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { bindFirstArguments } from 'utils/bindFirstArgument';
import * as OkeyGameActions from 'actions/OkeyGameActions';
import * as OkeyNetActions from 'actions/OkeyNetActions';
import * as OkeyChatActions from 'actions/Chatactions';
import { SeatDirection } from 'constants/AppConstants';
import { OkeyScoreboardDialog }
from 'components/OkeyScoreboardDialog/OkeyScoreboardDialog';
import OkeyMatchResultDialog
from 'components/OkeyMatchResultDialog/OkeyMatchResultDialog';
import OkeyRackWrapper from 'components/OkeyRackWrapper/OkeyRackWrapper';
import OkeyTopToolbar from 'components/OkeyTopToolbar/OkeyTopToolbar';
import OkeyTableToolbar from 'components/OkeyTableToolbar/OkeyTableToolbar';
import OkeyTableCenter from 'components/OkeyTableCenter/OkeyTableCenter';
import CustomDragLayer from 'components/CustomDragLayer/CustomDragLayer';
import MessageList from 'components/chat/MessageList';
import PrivateEastMessageList from 'components/chat/PrivateEastMessageList';
import PrivateNorthMessageList from 'components/chat/PrivateNorthMessageList';
import PrivateWestMessageList from 'components/chat/PrivateWestMessageList';
import PrivateSouthMessageList from 'components/chat/PrivateSouthMessageList';
import './_OkeyGame.scss';
function toJS(item) {
if (item === null) {
return null;
}
//var item1=item.toJS();
//if (item1.color==='BLACK') {
// var a='a';
//}
if (item == undefined) {
return;
}
return item.toJS();
}
function getRelativeDirection(selfSeat, direction) {
let relativeDirection = direction;
if (selfSeat >= 0) {
relativeDirection = (selfSeat - direction + 4) % 4;
}
return relativeDirection;
}
class OkeyGame extends React.Component {
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps,nextState) {
console.log(nextProps.gameStore.get('state'));//waiting
console.log(this.props.gameStore.get('state'));//waiting
console.log(this.state);
console.log(nextState);
if (nextProps.gameStore.get('state')==this.props.gameStore.get('state')) {
return false;
}
else {
return true;
}
}
render() {
const { dispatch, gameStore, gamePlay, playRules } = this.props;
let actions = bindActionCreators(OkeyGameActions, dispatch);
let netActions = bindActionCreators(OkeyNetActions, dispatch);
const currentTurn = gameStore.get('currentTurn');
const playState = {
selectedStone: gamePlay.get('selectedStone'),
gosterge: gamePlay.get('gosterge'),
middleStoneCount: gamePlay.get('middleStoneCount'),
currentTurn: currentTurn
};
if (playState.gosterge != undefined) {
window.localStorage.setItem('gostergeNumber', playState.gosterge._root.entries[0][1]);
window.localStorage.setItem('gostergeColor', playState.gosterge._root.entries[1][1]);
}
const hasOpenedStonesThisTurn = {
hasOpenedSequenceThisTurn: playRules.get('hasOpenedSequenceThisTurn'),
hasOpenedPairsThisTurn: playRules.get('hasOpenedPairsThisTurn')
};
const rules = {
canOpenSequence: playRules.get('canOpenSequence'),
canOpenPairs: playRules.get('canOpenPairs'),
canWithdraw: playRules.get('canWithdraw'),
canDiscard: playRules.get('canDiscard'),
canCollectOpen: playRules.get('canCollectOpen'),
canLeaveTaken: playRules.get('canLeaveTaken'),
canProcessStone: playRules.get('canProcessStone')
};
const discardMiniBoxes = {
discardMiniBoxPairs: gamePlay.get('pairs'),
discardMiniBoxSequence: gamePlay.get('sequence')
};
const selfSeat = gameStore.get('selfSeat');
const { westSeat, eastSeat, northSeat, southSeat } =
{
westSeat: getRelativeDirection(selfSeat, SeatDirection.WEST),
eastSeat: getRelativeDirection(selfSeat, SeatDirection.EAST),
northSeat: getRelativeDirection(selfSeat, SeatDirection.NORTH),
southSeat: getRelativeDirection(selfSeat, SeatDirection.SOUTH)
};
const players = {
selfSeat: selfSeat,
pSouth: {
seatId: southSeat,
discardStones: gamePlay.getIn(['discardStones', southSeat]),
profile: toJS(gameStore.getIn(['players', southSeat])),
dispatch: dispatch
},
pNorth: {
seatId: northSeat,
discardStones: gamePlay.getIn(['discardStones', northSeat]),
profile: toJS(gameStore.getIn(['players', northSeat])),
dispatch: dispatch
},
pEast: {
seatId: eastSeat,
discardStones: gamePlay.getIn(['discardStones', eastSeat]),
profile: toJS(gameStore.getIn(['players', eastSeat])),
dispatch: dispatch
},
pWest: {
seatId: westSeat,
discardStones: gamePlay.getIn(['discardStones', westSeat]),
profile: toJS(gameStore.getIn(['players', westSeat])),
dispatch: dispatch
}
};
let profiles = [
players.pSouth.profile,
players.pEast.profile,
players.pNorth.profile,
players.pWest.profile
];
localStorage.setItem("selfSeat", selfSeat);
localStorage.setItem("roomID", gameStore.get('id'));
if (selfSeat == 0)
profiles = [players.pSouth.profile,players.pEast.profile,players.pNorth.profile,players.pWest.profile];
else if (selfSeat == 1)
profiles = [players.pWest.profile,players.pSouth.profile,players.pEast.profile,players.pNorth.profile];
else if (selfSeat == 2)
profiles = [players.pNorth.profile,players.pWest.profile,players.pSouth.profile,players.pEast.profile];
else if (selfSeat == 3)
profiles = [players.pEast.profile,players.pNorth.profile,players.pWest.profile,players.pSouth.profile];
const matchState = {
name: gameStore.getIn(['options', 'name']),
maxRounds: gameStore.getIn(['options', 'rounds']),
stake: gameStore.getIn(['options', 'stakes']),
round: gameStore.get('round')
};
const owner = gamePlay.get('ownerID');
const scoreboard = gameStore.get('scoreboard');
const matchResult = gameStore.get('matchResult');
const restCountdown = gameStore.get('restCountdown');
const roomState = gameStore.get('roomState');
const { messageList } = this.props;
const { privateEastMessageList } = this.props;
const { privateNorthMessageList } = this.props;
const { privateWestMessageList } = this.props;
const { privateSouthMessageList } = this.props;
let chatActions = bindActionCreators(OkeyChatActions, dispatch);
// const dispatch1 = this.props
// each action has a first argument of room id
netActions = bindFirstArguments(netActions, gameStore.get('id'));
let from = gameStore.get('from');
let to = gameStore.get('to');
let gift = gameStore.get('gift');
let from1 = gameStore.get('from1');
let to1 = gameStore.get('to1');
let gift1 = gameStore.get('gift1');
let from2 = gameStore.get('from2');
let to2 = gameStore.get('to2');
let gift2 = gameStore.get('gift2');
let from3 = gameStore.get('from3');
let to3 = gameStore.get('to3');
let gift3 = gameStore.get('gift3');
let arayan = gameStore.get('arayan');
let aranan = gameStore.get('aranan');
return (
<div className="game-background" style={{background: 'url(http://okey101.xyz/staticImg/background.png)',backgroundSize:'cover'}}>
<div className="okey-game flex-centered-column">
<CustomDragLayer isMini={gamePlay.get('isOver') > 0}></CustomDragLayer>
<MessageList {...chatActions} {...netActions} messageList={messageList} />
<OkeyScoreboardDialog profiles={profiles}
scoreboard={scoreboard} />
<OkeyMatchResultDialog matchResult={matchResult}
{...netActions}
{...actions}
roomState={roomState}/>
<OkeyTopToolbar {...netActions}
{...matchState}
profiles={profiles}/>
<OkeyTableCenter {...actions}
{...netActions}
{...playState}
{...rules}
{...discardMiniBoxes}
{...players}
owner={owner}
messageList={messageList}
privateEastMessageList={privateEastMessageList}
privateNorthMessageList={privateNorthMessageList}
privateWestMessageList={privateWestMessageList}
privateSouthMessageList={privateSouthMessageList}
from={from}
to={to}
gift={gift}
from1={from1}
to1={to1}
gift1={gift1}
from2={from2}
to2={to2}
gift2={gift2}
from3={from3}
to3={to3}
gift3={gift3}
arayan={arayan}
aranan={aranan}
stones={gamePlay.get('stones')}/>
<OkeyRackWrapper {...actions}
{...netActions}
{...playState}
stones={gamePlay.get('stones')}
stoneGroups={gamePlay.get('stoneGroups')}/>
<OkeyTableToolbar {...actions}
{...netActions}
{...rules}
restCountdown={restCountdown}
currentTurn={currentTurn}
{...hasOpenedStonesThisTurn}
roomState={roomState}
stones={gamePlay.get('stones')}
{...discardMiniBoxes}
okeyStone={gamePlay.get('okeyStone')}/>
</div>
</div>
);
}
}
const mapStateToProps = (state => ({
gameStore: state.gameStore,
gamePlay: state.gamePlay,
playRules: state.playRules,
messageList: state.MessageList,
privateEastMessageList: state.PrivateEastMessageList,
privateNorthMessageList: state.PrivateNorthMessageList,
privateWestMessageList: state.PrivateWestMessageList,
privateSouthMessageList: state.PrivateSouthMessageList
}));
const OkeyGameWithDnD = DragDropContext(HTML5Backend)(OkeyGame);
export default connect(mapStateToProps)(OkeyGameWithDnD);
编辑:使用 Aftab Khan 指令,我将组件更改为 PureComponent,但页面打不开,控制台中也没有错误
我改成
const mapStateToProps = (state => ({
gameStore: toJS(state.gameStore),
gamePlay: toJS(state.gamePlay),
playRules: toJS(state.playRules),
messageList: toJS(state.MessageList),
privateEastMessageList: toJS(state.PrivateEastMessageList),
privateNorthMessageList: toJS(state.PrivateNorthMessageList),
privateWestMessageList: toJS(state.PrivateWestMessageList),
privateSouthMessageList: toJS(state.PrivateSouthMessageList)
}));
但还是不行 然后我把它改成这个
const mapStateToProps = (state => ({
gameStore: state.gameStore.toJS(),
gamePlay: state.gamePlay.toJS(),
playRules: state.playRules.toJS(),
messageList: state.MessageList.toJS(),
privateEastMessageList: state.PrivateEastMessageList.toJS(),
privateNorthMessageList: state.PrivateNorthMessageList.toJS(),
privateWestMessageList: state.PrivateWestMessageList.toJS(),
privateSouthMessageList: state.PrivateSouthMessageList.toJS()
}));
但它仍然无法在浏览器中打开
看来你需要 React.PureComponent
。
这是它的link。 Link
基本上它所做的是在渲染每个组件之前,它会检查组件的道具或状态是否有任何变化。如果没有变化,它不会重新渲染。
看起来您在 reducer 中使用了不可变数据结构。在你的 mapStateToProps 中,将所有不可变数据更改为调用 toJS()
方法的普通 JS 对象。然后 PureComponent 将按预期工作。
关于您的组件,我注意到的很少
render
方法对子组件进行大量初始化shouldComponentUpdate
是不必要的,因为它只处理道具(这是预期的,因为你所有的状态都在 redux 商店中)。PureComponent 是不必要的,因为您正在使用
connect()
将它连接到商店。您的组件没有状态,它更好地发挥作用 components created using a simple es6 arrow function
对于 2. 和 3. 请参考 note 优化 connect()
为您创建容器。
现在,如果不检查组件的每一行,就不可能告诉您为什么组件每秒都在渲染。但是,仔细考虑以下内容可以帮助您确保仅在必要时节俭地触发重新渲染。
1.保持 render()
方法尽可能轻量级
render
可能是所有组件中调用次数最多的方法。更臃肿的是你渲染周期会很慢。你可以把你 localStorage.setItems
全部移到 componentWillReceiveProps
。这些 synchronous LocalStorage calls 中的每一个都占用了渲染时间。
2。删除 shouldComponentUpdate
。相反,只将那些道具传递给它绝对需要的组件。制作尽可能多的组件无状态纯函数
shouldComponentUpdate 是组件的逃生舱口,组件需要渲染更多道具。 sCU 的缺点:它在每个组件重新渲染之前运行。在某些情况下,它可以减慢速度而不是加快速度。请参阅 jimfb 的评论 here。这支持我将尽可能多的组件转换为无状态功能组件的建议 - 可能包括您在此处发布的组件
3。如果您的组件是无状态的,则不需要 PureComponent javascript 函数只接受它们需要的道具。