React.js. Начало работы. Часть 10 из 12
27.10.2019
Теги: JavaScript • React.js • Web-разработка • Компонент • Фреймворк
Оптимизация приложения
Быстрая работа с DOM — одно из самых больших преимуществ React. Но для оптимизации приложения, нужно позаботиться о том, чтобы не вызывать метод render()
компонентов приложения без необходимости. Приложения, с которыми мы работали до этого момента, никогда явно не вызывали метод render()
, это происходило автоматически.
Давайте уточним — метод вызывается автоматически в трех ситуациях:
- Обновляется свойство компонента
- Обновляется состояние компонента
- Вызывается метод
render()
родительского компонента
Все три ситуации могут могут привести к изменению визуального представления компонента. Наша задача — предотвратить вызов методов render()
, когда в этом нет необходимости.
Рассмотрим еще раз выдвижное меню. И расставим вызов console.log()
внутри всех методов render()
:
import React, {Component} from 'react'; import ShowButton from './ShowButton'; import SlideMenu from './SlideMenu'; class MenuContainer extends Component { /*.....*/ render() { console.log('Метод render() компонента MenuContainer'); return ( <div> <ShowButton handleClick={this.toggleMenu} /> <SlideMenu handleClick={this.toggleMenu} visibility={this.state.visible} /> </div> ); } } export default MenuContainer;
import React, {Component} from 'react'; import HideButton from './HideButton'; import './SlideMenu.css'; class SlideMenu extends Component { render() { console.log('Метод render() компонента SlideMenu'); var visibility = 'hide'; if (this.props.visibility) { visibility = 'show'; } return ( <div id="slide-menu" className={visibility}> <HideButton handleClick={this.props.handleClick} /> <h3><a href="#">Первый элемент меню</a></h3> <h3><a href="#">Второй элемент меню</a></h3> <h3><a href="#">Третий элемент меню</a></h3> <h3><a href="#">Четвертый элемент меню</a></h3> <h3><a href="#">Пятый элемент меню</a></h3> <h3><a href="#">Шестой элемент меню</a></h3> <h3><a href="#">Седьмой элемент меню</a></h3> </div> ); } } export default SlideMenu;
import React, {Component} from 'react'; import './ShowButton.css'; class ShowButton extends Component { render() { console.log('Метод render() компонента ShowButton'); return ( <button id="show-button" onClick={this.props.handleClick}><span>»</span></button> ); } } export default ShowButton;
import React, {Component} from 'react'; import './HideButton.css'; class HideButton extends Component { render() { console.log('Метод render() компонента HideButton'); return ( <button id="hide-button" onClick={this.props.handleClick}><span>«</span></button> ); } } export default HideButton;
Запустим приложение, откроем консоль разработчика, кликнем кнопку открытия меню, а потом кнопку закрытия:
MenuContainer.js:24 Метод render() компонента MenuContainer ShowButton.js:6 Метод render() компонента ShowButton SlideMenu.js:7 Метод render() компонента SlideMenu HideButton.js:6 Метод render() компонента HideButton MenuContainer.js:17 Изменение состояния меню MenuContainer.js:24 Метод render() компонента MenuContainer ShowButton.js:6 Метод render() компонента ShowButton SlideMenu.js:7 Метод render() компонента SlideMenu HideButton.js:6 Метод render() компонента HideButton MenuContainer.js:17 Изменение состояния меню MenuContainer.js:24 Метод render() компонента MenuContainer ShowButton.js:6 Метод render() компонента ShowButton SlideMenu.js:7 Метод render() компонента SlideMenu HideButton.js:6 Метод render() компонента HideButton
Нетрудно заметить, что свойство handleClick
, которое передается компоненту ShowButton
не изменяется при каждом открытии и закрытии меню.Так что нужно предотвратить вызов метода render()
:
import React, {Component} from 'react'; import './ShowButton.css'; class ShowButton extends Component { shouldComponentUpdate(newProps, newState) { return false; } render() { console.log('Метод render() компонента ShowButton'); return ( <button id="show-button" onClick={this.props.handleClick}><span>»</span></button> ); } } export default ShowButton;
Снова запустим приложение, откроем консоль разработчика, кликнем кнопку открытия меню, а потом кнопку закрытия:
MenuContainer.js:24 Метод render() компонента MenuContainer ShowButton.js:9 Метод render() компонента ShowButton SlideMenu.js:7 Метод render() компонента SlideMenu HideButton.js:6 Метод render() компонента HideButton MenuContainer.js:17 Изменение состояния меню MenuContainer.js:24 Метод render() компонента MenuContainer SlideMenu.js:7 Метод render() компонента SlideMenu HideButton.js:6 Метод render() компонента HideButton MenuContainer.js:17 Изменение состояния меню MenuContainer.js:24 Метод render() компонента MenuContainer SlideMenu.js:7 Метод render() компонента SlideMenu HideButton.js:6 Метод render() компонента HideButton
Аналогично, нужно предотвратить вызов метода render()
компонента HideButton
:
import React, {Component} from 'react'; import './HideButton.css'; class HideButton extends Component { shouldComponentUpdate(newProps, newState) { return false; } render() { console.log('Метод render() компонента HideButton'); return ( <button id="hide-button" onClick={this.props.handleClick}><span>«</span></button> ); } } export default HideButton;
Еще раз запустим приложение, откроем консоль разработчика, кликнем кнопку открытия меню, а потом кнопку закрытия:
MenuContainer.js:24 Метод render() компонента MenuContainer ShowButton.js:9 Метод render() компонента ShowButton SlideMenu.js:7 Метод render() компонента SlideMenu HideButton.js:9 Метод render() компонента HideButton MenuContainer.js:17 Изменение состояния меню MenuContainer.js:24 Метод render() компонента MenuContainer SlideMenu.js:7 Метод render() компонента SlideMenu MenuContainer.js:17 Изменение состояния меню MenuContainer.js:24 Метод render() компонента MenuContainer SlideMenu.js:7 Метод render() компонента SlideMenu
Мы здесь поступили предельно просто, всегда возвращая false
. Но лучше проверять значение свойства:
shouldComponentUpdate(newProps, newState) { if (newProps.handleClick === this.props.handleClick) { return false; } else { return true; } }
Использование компонента PureComponent
Чтобы вручную не определять изменение свойства или состояния, можно использовать специальный компонент PureComponent
:
import React, {PureComponent} from 'react'; import './ShowButton.css'; class ShowButton extends PureComponent { render() { console.log('Метод render() компонента ShowButton'); return ( <button id="show-button" onClick={this.props.handleClick}><span>»</span></button> ); } } export default ShowButton;
import React, {PureComponent} from 'react'; import './HideButton.css'; class HideButton extends PureComponent { render() { console.log('Метод render() компонента HideButton'); return ( <button id="hide-button" onClick={this.props.handleClick}><span>«</span></button> ); } } export default HideButton;
MenuContainer.js:24 Метод render() компонента MenuContainer ShowButton.js:6 Метод render() компонента ShowButton SlideMenu.js:7 Метод render() компонента SlideMenu HideButton.js:6 Метод render() компонента HideButton MenuContainer.js:17 Изменение состояния меню MenuContainer.js:24 Метод render() компонента MenuContainer SlideMenu.js:7 Метод render() компонента SlideMenu MenuContainer.js:17 Изменение состояния меню MenuContainer.js:24 Метод render() компонента MenuContainer SlideMenu.js:7 Метод render() компонента SlideMenu
Поиск: JavaScript • React.js • Web-разработка • Компонент • Фреймворк • render • Оптимизация • PureComponent