Merge pull request #125 from Gargron/fix-useless-rerenders

Remove function binds in render wherever possible, use PureComponent
nolan/hinaloe-test
Etienne Lemay 2017-09-30 11:42:03 -04:00 committed by GitHub
commit bbd4fbe764
6 changed files with 76 additions and 46 deletions

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import SVGs from '../svgs'
export default class Anchors extends React.Component {
export default class Anchors extends React.PureComponent {
constructor(props) {
super(props)
@ -14,6 +14,15 @@ export default class Anchors extends React.Component {
this.state = {
selected: defaultCategory.name
}
this.handleClick = this.handleClick.bind(this)
}
handleClick (e) {
var index = e.currentTarget.getAttribute('data-index')
var { categories, onAnchorClick } = this.props
onAnchorClick(categories[index], index)
}
render() {
@ -33,7 +42,8 @@ export default class Anchors extends React.Component {
<span
key={name}
title={i18n.categories[name.toLowerCase()]}
onClick={() => onAnchorClick(category, i)}
data-index={i}
onClick={this.handleClick}
className={`emoji-mart-anchor ${isSelected ? 'emoji-mart-anchor-selected' : ''}`}
style={{ color: isSelected ? color : null }}
>

View File

@ -5,6 +5,13 @@ import frequently from '../utils/frequently'
import { Emoji } from '.'
export default class Category extends React.Component {
constructor(props) {
super(props)
this.setContainerRef = this.setContainerRef.bind(this)
this.setLabelRef = this.setLabelRef.bind(this)
}
componentDidMount() {
this.parent = this.container.parentNode
@ -133,16 +140,13 @@ export default class Category extends React.Component {
}
}
return <div ref={this.setContainerRef.bind(this)} className={`emoji-mart-category ${emojis && !emojis.length ? 'emoji-mart-no-results' : ''}`} style={containerStyles}>
return <div ref={this.setContainerRef} className={`emoji-mart-category ${emojis && !emojis.length ? 'emoji-mart-no-results' : ''}`} style={containerStyles}>
<div style={labelStyles} data-name={name} className='emoji-mart-category-label'>
<span style={labelSpanStyles} ref={this.setLabelRef.bind(this)}>{i18n.categories[name.toLowerCase()]}</span>
<span style={labelSpanStyles} ref={this.setLabelRef}>{i18n.categories[name.toLowerCase()]}</span>
</div>
{emojis && emojis.map((emoji) =>
Emoji({
emoji: emoji,
...emojiProps
})
Emoji({ emoji: emoji, ...emojiProps })
)}
{emojis && !emojis.length &&

View File

@ -32,7 +32,7 @@ const I18N = {
},
}
export default class Picker extends React.Component {
export default class Picker extends React.PureComponent {
constructor(props) {
super(props)
@ -115,6 +115,19 @@ export default class Picker extends React.Component {
}
this.categories.unshift(SEARCH_CATEGORY)
this.setAnchorsRef = this.setAnchorsRef.bind(this)
this.handleAnchorClick = this.handleAnchorClick.bind(this)
this.setSearchRef = this.setSearchRef.bind(this)
this.handleSearch = this.handleSearch.bind(this)
this.setScrollRef = this.setScrollRef.bind(this)
this.handleScroll = this.handleScroll.bind(this)
this.handleScrollPaint = this.handleScrollPaint.bind(this)
this.handleEmojiOver = this.handleEmojiOver.bind(this)
this.handleEmojiLeave = this.handleEmojiLeave.bind(this)
this.handleEmojiClick = this.handleEmojiClick.bind(this)
this.setPreviewRef = this.setPreviewRef.bind(this)
this.handleSkinChange = this.handleSkinChange.bind(this)
}
componentWillReceiveProps(props) {
@ -206,7 +219,7 @@ export default class Picker extends React.Component {
handleScroll() {
if (!this.waitingForPaint) {
this.waitingForPaint = true
window.requestAnimationFrame(this.handleScrollPaint.bind(this))
window.requestAnimationFrame(this.handleScrollPaint)
}
}
@ -368,17 +381,17 @@ export default class Picker extends React.Component {
return <div style={{width: width, ...style}} className='emoji-mart'>
<div className='emoji-mart-bar'>
<Anchors
ref={this.setAnchorsRef.bind(this)}
ref={this.setAnchorsRef}
i18n={this.i18n}
color={color}
categories={this.categories}
onAnchorClick={this.handleAnchorClick.bind(this)}
onAnchorClick={this.handleAnchorClick}
/>
</div>
<Search
ref={this.setSearchRef.bind(this)}
onSearch={this.handleSearch.bind(this)}
ref={this.setSearchRef}
onSearch={this.handleSearch}
i18n={this.i18n}
emojisToShowFilter={emojisToShowFilter}
include={include}
@ -387,7 +400,7 @@ export default class Picker extends React.Component {
autoFocus={autoFocus}
/>
<div ref={this.setScrollRef.bind(this)} className='emoji-mart-scroll' onScroll={this.handleScroll.bind(this)}>
<div ref={this.setScrollRef} className='emoji-mart-scroll' onScroll={this.handleScroll}>
{this.getCategories().map((category, i) => {
return <Category
ref={this.setCategoryRef.bind(this, `category-${i}`)}
@ -407,9 +420,9 @@ export default class Picker extends React.Component {
sheetSize: sheetSize,
forceSize: native,
backgroundImageFn: backgroundImageFn,
onOver: this.handleEmojiOver.bind(this),
onLeave: this.handleEmojiLeave.bind(this),
onClick: this.handleEmojiClick.bind(this),
onOver: this.handleEmojiOver,
onLeave: this.handleEmojiLeave,
onClick: this.handleEmojiClick,
}}
/>
})}
@ -417,7 +430,7 @@ export default class Picker extends React.Component {
{showPreview && <div className='emoji-mart-bar'>
<Preview
ref={this.setPreviewRef.bind(this)}
ref={this.setPreviewRef}
title={title}
emoji={emoji}
emojiProps={{
@ -430,7 +443,7 @@ export default class Picker extends React.Component {
}}
skinsProps={{
skin: skin,
onChange: this.handleSkinChange.bind(this)
onChange: this.handleSkinChange
}}
/>
</div>}

View File

@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import { Emoji, Skins } from '.'
import { getData } from '../utils'
export default class Preview extends React.Component {
export default class Preview extends React.PureComponent {
constructor(props) {
super(props)
this.state = { emoji: null }
@ -31,11 +31,7 @@ export default class Preview extends React.Component {
return <div className='emoji-mart-preview'>
<div className='emoji-mart-preview-emoji'>
{Emoji({
key: emoji.id,
emoji: emoji,
...emojiProps,
})}
{Emoji({ key: emoji.id, emoji: emoji, ...emojiProps })}
</div>
<div className='emoji-mart-preview-data'>
@ -55,10 +51,7 @@ export default class Preview extends React.Component {
} else {
return <div className='emoji-mart-preview'>
<div className='emoji-mart-preview-emoji'>
{idleEmoji && idleEmoji.length && Emoji({
emoji: idleEmoji,
...emojiProps,
})}
{idleEmoji && idleEmoji.length && Emoji({ emoji: idleEmoji, ...emojiProps })}
</div>
<div className='emoji-mart-preview-data'>

View File

@ -2,7 +2,14 @@ import React from 'react'
import PropTypes from 'prop-types'
import emojiIndex from '../utils/emoji-index'
export default class Search extends React.Component {
export default class Search extends React.PureComponent {
constructor (props) {
super(props)
this.setRef = this.setRef.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleChange() {
var value = this.input.value
@ -28,9 +35,9 @@ export default class Search extends React.Component {
return <div className='emoji-mart-search'>
<input
ref={this.setRef.bind(this)}
ref={this.setRef}
type='text'
onChange={this.handleChange.bind(this)}
onChange={this.handleChange}
placeholder={i18n.search}
autoFocus={autoFocus}
/>

View File

@ -1,16 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'
export default class Skins extends React.Component {
export default class Skins extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
opened: false,
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(skin) {
handleClick(e) {
var skin = e.currentTarget.getAttribute('data-skin')
var { onChange } = this.props
if (!this.state.opened) {
@ -39,9 +42,9 @@ export default class Skins extends React.Component {
className={`emoji-mart-skin-swatch ${selected ? 'emoji-mart-skin-swatch-selected' : ''}`}
>
<span
onClick={() => this.handleClick(skinTone)}
className={`emoji-mart-skin emoji-mart-skin-tone-${skinTone}`}>
</span>
onClick={this.handleClick}
data-skin={skinTone}
className={`emoji-mart-skin emoji-mart-skin-tone-${skinTone}`} />
</span>
)
}