Использование toComponentUpdate для повторной рендеринга блочного компонента каждую секунду

Эта игра разработана с реакцией и сокращением. Я не разработчик response-redux (я разработчик .net), но я должен продолжить этот проект, чтобы я был новым в реакции и сокращении   Эта игра слишком плохая в некоторых телефонах Android. Поэтому я анализирую проект. Я вижу, что метод рендеринга компонентов работает каждую секунду. В моем компоненте содержится более 30 других компонентов. Каждый раз, когда он воспроизводится, и это приводит к плохой производительности в некоторых старых Android-телефоны

Зачем реагировать компонент повторно на каждую секунду? Могу ли я заблокировать это? Я ищу эту проблему, я вижу, что это решение должно включать функцию CompompententUpdate

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 и это состояние такое же, nextProps.gameStore.get('state') и this.props.gameStore.get('state') тот же. Почему следующее состояние и текущее состояние одинаковы? Что мне делать? Я использую конструктор, но он все тот же здесь это мой код компонента

    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()
}));

но он все еще не открывается в браузере

Ответ 1

Есть несколько вещей, которые я заметил о вашем компоненте

  • render метод выполняет всю инициализацию для дочерних компонентов

  • shouldComponentUpdate не требуется, поскольку он имеет дело только с реквизитами (что ожидается, так как все ваше состояние находится в магазине redux).

  • PureComponent не нужно указывать, что вы подключаете его к хранилищу с помощью connect(). У вашего компонента нет состояния, его лучшего бытия и функциональных компонентов созданных с помощью простой функции стрелок es6

Для 2. и 3. обратитесь к note об оптимизации connect() для вас, поскольку он создает контейнеры.

Теперь невозможно рассказать вам, почему ваши компоненты обрабатываются каждую секунду, не проверяя каждую строку ваших компонентов. Тем не менее, при тщательном рассмотрении следующего может помочь вам убедиться, что повторные рендеры запускаются экономно и только при необходимости.

1. Придерживайтесь render() как можно более легкого render, вероятно, является наиболее востребованным методом во всех компонентах. Больше раздутого медленного вы будете визуализировать циклы. Вы можете переместить все localStorage.setItems на componentWillReceiveProps. Каждый из этих синхронных вызовов LocalStorage занимает время рендеринга.

2. Удалите shouldComponentUpdate. Вместо этого передавайте только те реквизиты для компонентов, которые это абсолютно необходимо. Сделать так много компонентов безстоящих чистых функций

shouldComponentUpdate - это управляющий штрих для компонентов, которые используют больше реквизитов, которые им нужно визуализировать. Недостаток sCU: он выполняется перед каждым повторным рендерингом компонентов. В некоторых случаях он может замедляться, а не ускоряться. См. Этот комментарий здесь от jimfb. Это поддерживает мое предложение превратить как можно больше компонентов в компоненты функций без состояния - включая, возможно, компонент, который вы разместили здесь.

3. PureComponent не понадобится, если ваши компоненты - это функции без состояния в javascript, использующие только те реквизиты, которые им нужны.

Ответ 2

Похоже, вам нужно React.PureComponent. Вот ссылка на него. Ссылка

В основном то, что он делает, - это до того, как выполнить рендеринг каждого компонента, он будет проверять, есть ли у компонента какие-либо изменения в реквизитах или состоянии. Если изменений нет, он не будет повторно.

Похоже, вы используете неизменяемые структуры данных в своем редукторе. В ur mapStateToProps измените все неизменяемые данные на обычные объекты JS, вызвав метод toJS(). Затем PureComponent будет работать по назначению.