åå¿ããã©ãŒãã³ã¹ã«ã€ããŠ
Reactã¯éåžžã«çç£çãªãã¬ãŒã ã¯ãŒã¯ãšã¯èããããŸããã ããã«ãããå€æ°ã®èŠçŽ ãæã€é«éã§åçãªããŒãžãäœæã§ããŸãã
ããããããŒãžã«å€ãã®èŠçŽ ããããçµã¿èŸŒã¿ã®ãªã¢ã¯ã·ã§ã³ããã©ãŒãã³ã¹ã§ã¯äžååãªå ŽåããããŸãã 次ã«ãæé©åã®ããã®ããŸããŸãªææ³ãé©çšããå¿ èŠããããŸãã
reactã§æžãããããŒãžã¯ãå¥ã ã®ã³ã³ããŒãã³ãã§æ§æãããŠããŸãã ãããã®ããããã¯ãããŒãžã®ç¹å®ã®éšåã®å€èŠ³ãæ åœããŸãã ãã®å€èŠ³ã¯ãã³ã³ããŒãã³ãã«æž¡ããããã©ã¡ãŒã¿ãŒïŒããããã£ïŒã«ãã£ãŠç°ãªããŸãã ã€ãã³ããçºçãããšïŒããšãã°ããŠãŒã¶ãŒã®ã¢ã¯ã·ã§ã³äžãŸãã¯ãããã¯ãŒã¯çµç±ã§ããŒã¿ãåä¿¡äžïŒãããããã£ãå€æŽãããå ŽåããããŸãã ã³ã³ããŒãã³ãã®ããããã£ãå€æŽãããå Žåããããã®å€æŽããŠãŒã¶ãŒã®ç»é¢ã«è¡šç€ºãããããã«åæç»ããå¿ èŠããããŸãã
ã€ãã³ããçºçãããšããããã®åå ãšãªã£ãŠããã³ã³ããŒãã³ãã®ããããã£ãå€æŽãããŠããªããŠããããŒãžã®äžéšãåæç»ã§ããŸãã ãã®ãããªããŒããå€æ°ããå ŽåããŠãŒã¶ãŒã®æäœã«ãã£ãŠãã¬ã³ããªã³ã°ã«ããªãã®æéãããããããŒãžã€ã³ã¿ãŒãã§ã€ã¹ãšã®å¯Ÿè©±æã«é¡èãªé 延ãçºçããå¯èœæ§ããããŸãã ãã®ãããªããã©ãŒãã³ã¹ã®åé¡ã«å¯ŸåŠããäž»ãªæ¹æ³ã¯ãããããã£ãå€æŽãããŠããªãå Žåãã³ã³ããŒãã³ãã®åæç»ããã£ã³ã»ã«ããããšã§ãã ã€ãŸããã€ãã³ããçºçããå Žåãããããã£ãšå€èŠ³ããã®ã€ãã³ãã«åœ±é¿ããããŒãžäžã«èŠçŽ ã®ã¿ãåæç»ããå¿ èŠããããŸãã ãããè¡ãã«ã¯ãReactã³ã³ããŒãã³ããäœæãããšãã«shouldComponentUpdateã¡ãœãããå®çŸ©ããããReact.Componentã®ä»£ããã«React.PureComponentã芪ã¯ã©ã¹ãšããŠäœ¿çšããå¿ èŠããããŸãã
åæç»ãäžèŠãªå ŽåãshouldComponentUpdateã¡ãœããã¯falseãè¿ãå¿ èŠããããŸãã ãŸããReact.PureComponentã¯ã©ã¹ã§ã¯ããã®ã¡ãœããã¯æ¢ã«å®è£ ãããŠããŸãã ãã¹ãŠã®åä¿¡ããããã£ããã§ãã¯ããããããã£ãå€æŽãããŠããªãå Žåãã³ã³ããŒãã³ãã¯åæç»ãããŸããã
shouldComponentUpdateã®äŸïŒ
import * as React from 'react'; class Component extends React.Component { shouldComponentUpdate(nextProps) { return this.props.value !== nextProps.value } render() { return <div>...</div>; } }
React.PureComponentã®äŸïŒ
import * as React from 'react'; class Component extends React.PureComponent { render() { return <div>...</div>; } }
æé©åãæ©èœããªãå Žå
shouldCompenentUpdateããã³React.PureComponentã®åäœåçã¯ãå€ãããããã£ãšæ°ããããããã£ãæ¯èŒããããšã«åºã¥ããŠããŸãã ããããã£ãå€æŽãããŠããªãå Žåãã³ã³ããŒãã³ãã®å€èŠ³ã¯æŽæ°ãããŸããã
ãããã£ãŠãå¿
èŠãªå Žåã«ã®ã¿ããããã£ãå€æŽããããã«ããŠãã ããã
ãã ããã³ã³ããŒãã³ããäžèŠãªå Žåã«æ°ããããããã£ããã£ããåãåã£ãŠããŸãå ŽåããããŸãã
ããã¯ããã€ã³ãã¡ãœãããç¢å°é¢æ°ããªãã©ã«ãªããžã§ã¯ãããŸãã¯renderã¡ãœããã®ãã¹ãŠã®åŒã³åºãã§æ°ãããªããžã§ã¯ããäœæãããã®ä»ã®æ§é ã䜿çšãããšãã«çºçããå¯èœæ§ããããŸãã
æé©åãæ©èœããªãå ŽåïŒ
class ParentComponent extends React.Component { _onClick() { doSomehing(); } render() { return ( <div> <Child1 onClick={this._onClick.bind(this)}/> <Child2 onClick={() => this._onClick()}/> <Child3 data={{id: this.props.id, value: this.props.value}}/> <Child4 items={this.props.items.map((item) => {.....})}/> </div> ); } }
ãã€ã³ãé¢æ°ãšç¢å°é¢æ°ã¯ãå®è¡ã®ãã³ã«é¢æ°ã®æ°ããã€ã³ã¹ã¿ã³ã¹ãè¿ããŸãã
ãã€ã³ãå®è¡çµæã®æ¯èŒïŒ
this._onClick.bind(this) === this._onClick.bind(this) // false () => this._onClick() === () => this._onClick() //false
ãããã£ãŠãããã§ã¯æåã®2ã€ã®ã³ã³ããŒãã³ããæ°ããonClickããããã£ãæ¯ååãåããŸãã
Child3ã¯dataããããã£ã§æ°ãããªããžã§ã¯ããåãåãã4çªç®ã¯ã¢ã€ãã ã§æ°ããé
åãåãåããŸãã
ãã®ãããªæ§é ã¯é¿ããŠãã ããã ãããã䜿çšããå ŽåãshouldComponentUpdateãŸãã¯React.PureComponentã䜿çšããŠå®è¡ãããããã©ãŒãã³ã¹ã®æé©åã¯ãæ°ããããããã£ã®ããã«æ©èœããŸããã
ååãšããŠããã®ãããªshouldComponentUpdateã®å®è£ ãèšè¿°ã§ããŸãããã®å®è£ ã§ã¯ãäžéšã®ããããã£ãžã®å€æŽã¯ç¡èŠãããæŽæ°ã¯è¡ãããŸããã ãã ãããã®æ¹æ³ã¯ãã¹ãŠã®ç¶æ³ã§äœ¿çšã§ããããã§ã¯ãããŸããã ãŸããå€ãã®ããããã£ãããå Žåããã®ãããªå®è£ ã«ã¯ããªãå€æ°ã®ãã§ãã¯ãå«ãŸããããšããããããããšã©ãŒããã°ã®åå ã«ãªãå¯èœæ§ããããŸãã ãŸããæ°ããããããã£ãè¿œå ããå Žåã¯ãshouldComponentUpdateã¡ãœããããã¡ã€ãã©ã€ãºããå¿ èŠãããããããã®ã³ãŒãã®ä¿å®ã¯ããå°é£ã§ãã 次ã«ããã®ã¢ãããŒãã§ã¯ãshouldComponentUpdateãå®è£ ãããŠããã³ã³ããŒãã³ãã¯ãã©ã®ããããã£ãç¡èŠã§ããããæ£ç¢ºã«å€æããããã«ã䜿çšããå Žæãšç¶æ³ãæ£ç¢ºã«ææ¡ããå¿ èŠããããŸãã ãããŠãããã䜿çšãããå Žæã§ã¯ããããã®ããããã£ã«æ°ããå€ã転éããªãããã«å éšå®è£ ãç¥ãå¿ èŠããããŸãããã®å€æŽã¯äžå¿ èŠãªåæç»ã«ã€ãªãããŸãã ããã¯ãã³ã³ããŒãã³ãã®ã«ãã»ã«åã倧ããæãªããããã¯ã»ãšãã©ã®å ŽåæãŸãããããŸããã
æ§èœè©Šéšçµæ
å€ãã®å Žåãã³ãŒãã®èšè¿°æããã³ã³ãŒãã®ã¬ãã¥ãŒæã«ãæéãè²»ãããŠãã®ãããªåé¡ã«æ³šæãæãã¹ããã©ããã«ã€ããŠçåãçããŸãã æ°ããããããã£ãã³ã³ããŒãã³ãã«æž¡ãããšãããã©ãŒãã³ã¹ã«äžãã圱é¿ãå€æããããã«ãå°ããªãã¹ãããŒãžãäœæãããŸããã https://megazazik.github.io/react-perf-test/ã«ãããŸã
ãã®ãããžã§ã¯ãã䜿çšãããšãæ°ããããããã£ãåãåããã³ã«ããŸãããããã£ãå€æŽãããŠããªãå Žåã«ãå€æ°ã®å°ããªã³ã³ããŒãã³ãã®æŽæ°æéã枬å®ã§ããŸãã ãã¹ãã«ã¯ãããŸããŸãªã³ã³ããŒãã³ãã䜿çšãããŸããã
- ã¹ããŒããã«-React.Componentããç¶æ¿
- ã¹ããŒããã«-React.PureComponentããç¶æ¿
- ã¹ããŒãã¬ã¹-ã·ã³ãã«ãªæ©èœ
- htmlèŠçŽ ïŒdivïŒ
ãããžã§ã¯ãããŒãžãéããšãæ°åã®èŠçŽ ã®ãªã¹ãã衚瀺ãããŸãã ã¢ã€ãã ãã¯ãªãã¯ããããããŒãããšãéžæããã¢ã€ãã ãã¢ã¯ãã£ãã«ãªãããªã¹ããåæç»ãããŸãã åæã«ãéžæãããã©ã¡ãŒã¿ãŒã«å¿ããŠãç¶æ ãå€æŽãããŠããªãèŠçŽ ã¯ãç¢å°é¢æ°ã®äœ¿çšã«ããåãããããã£ãŸãã¯æ°ããããããã£ãåãåããŸãã
1000ã¢ã€ãã ã®æŽæ°æéïŒ
ããã€ã¹ããã©ãŠã¶ | æé©å | ãã¥ã¢ãmc | ã¹ããŒããã«ãmc | ã¹ããŒãã¬ã¹ãmc | htmlãmc |
---|---|---|---|---|---|
ãã¹ã¯ããããChrome | ãã | 6.5 | 6.3 | 5.8 | 3,5 |
ãã¹ã¯ããããChrome | ã¯ã | 3.3 | 4.9 | 4.3 | 2,5 |
ãã¹ã¯ããããFirefox | ãã | 13.7 | 11.9 | 11.5 | 7.3 |
ãã¹ã¯ããããFirefox | ã¯ã | 5,4 | 8.5 | 7.6 | 4.4 |
ãã¹ã¯ãããããšããž | ãã | 19.6 | 16,2 | 13.5 | 8.6 |
ãã¹ã¯ãããããšããž | ã¯ã | 8.1 | 11.5 | 8.7 | 4.7 |
ã¢ãã€ã«ãChrome | ãã | 31.1 | 30,2 | 29.6 | 19.3 |
ã¢ãã€ã«ãChrome | ã¯ã | 16.7 | 25.8 | 21.5 | 14.8 |
ç¹å®ã®æ°å€ã¯ãããŒãžãéãããã€ã¹ãšãã©ãŠã¶ãŒãã¡ã¢ãªã®ç¶æ ãããã»ããµã®è² è·ã«ãã£ãŠå€§ããç°ãªãå ŽåããããŸãã ãã ããæé©åãããšæé©åãªãã®ã¬ã³ããªã³ã°ããã©ãŒãã³ã¹ã®çžå¯Ÿçãªéãã¯ãåžžã«ã»ãŒåãã¬ãã«ã«ç¶æããå¿ èŠããããŸãã
çµæãããã€ã¹ã«é¢é£ããçµæãšæ¯èŒã§ããŸãã
æé©ãªã¬ã³ããªã³ã°æéã¯ãããã€ã¹ç»é¢ã®æŽæ°æã«ãã©ãŠã¶ããã¬ãŒã ãã¹ãããããªããããªæéãšèŠãªãããšãã§ããŸãã ææ°ã®ç»é¢ã®ã»ãšãã©ã¯ãå°ãªããšã60ãã¬ãŒã /ç§ã®ãªãã¬ãã·ã¥ã¬ãŒãããµããŒãããŠããŸãã ç»é¢ã¯å°ãªããšã16.6ããªç§ããšã«æŽæ°ãããããšãããããŸãã ãããã£ãŠãè¿œå ã®è² è·ã®å¯èœæ§ãèæ ®ããŠããã¹ãŠã®ããŒãžã³ã³ããŒãã³ãã®æŽæ°ã10ããªç§ä»¥å ã«è¡ãããããšãæãŸããã§ãã
ãã¹ãçµæã¯ãããããã£ãå€æŽãããªãå ŽåãPureComponentããã³htmlèŠçŽ ããç¶æ¿ãããã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°æéã倧å¹
ã«ççž®ãããããšã瀺ããŠããŸãã
ãã¹ãã§ã¯ãããããã£ã®äžå€æ§ã¯ä»ã®ã¿ã€ãã®ã³ã³ããŒãã³ãã®ããã©ãŒãã³ã¹ã«ã圱é¿ããŸãã ããããããã¯éåžžã«å°ãããåæç»ã®ãã£ã³ã»ã«ãšã¯é¢ä¿ãããŸããããåãåã£ãããããã£ã¯æçµçã«ããŒã¯ã¢ããå
ã®åãdivèŠçŽ ã«è»¢éããããã§ã«æé©åãããŠããŸãã
ãã¹ãäžãæå°ã®ã³ã³ããŒãã³ãã䜿çšãããŸããã ãµã€ãºã倧ãããªããšãçç£æ§ã®åäžã¯å¢å ããã ãã§ãã ãã®å¹æã¯ããã¹ããããžã§ã¯ãã§[ãªã¹ãã®ç Žæ]ãªãã·ã§ã³ãæå¹ã«ãªã£ãŠããå Žåã倧ãŸãã«æšå®ã§ããŸãã ãã®ã¢ãŒãã§ã¯ããªã¹ãå šäœããããã10åã®èŠçŽ ã®ã°ã«ãŒãã«åå²ãããŸãã 次ã«ã10ã°ã«ãŒãããšã«äžäœã¬ãã«ã®ã°ã«ãŒãã«é çªã«çµåãããŸãã ãã®çµæãããŒãžã¯10åã®ãµãã°ã«ãŒããå«ã10åã®ã°ã«ãŒãã§æ§æãããåãµãã°ã«ãŒãã«ã¯10åã®èŠçŽ ããããŸãã
ãã®å èš³ã¯ãå®éã®ããŒãžã®æ§æã«äŒŒãŠããŸãã éåžžãããŒãžã«ã¯ãå°ããªãã¹ããããã³ã³ããŒãã³ããå«ãããã€ãã®å€§ããªã³ã³ããŒãã³ããå«ãŸããŸãã
ãã®ã¢ãŒãã§ã¯ãææªã®ç¶æ³ãã€ãã³ãã®çºçæã«ããŒãžã®ãã¹ãŠã®èŠçŽ ãåæç»ãããç¶æ³ãããã³ç¶æ³ã®éã®ããã©ãŒãã³ã¹ã®éããè©äŸ¡ã§ããŸãã ããããã£ãå€æŽãããèŠçŽ ã®ã¿ãæŽæ°ãããå Žåã
ããã€ã¹ããã©ãŠã¶ | æé©å | ãã¥ã¢ãmc | ã¹ããŒããã«ãmc | ã¹ããŒãã¬ã¹ãmc | htmlãmc |
---|---|---|---|---|---|
ãã¹ã¯ããããChrome | ãã | 8.7 | 8.3 | 8.0 | 6.1 |
ãã¹ã¯ããããChrome | ã¯ã | 0.9 | 0.9 | 0.9 | 0.8 |
ãã¹ã¯ããããFirefox | ãã | 19.1 | 16.3 | 15.4 | 12.6 |
ãã¹ã¯ããããFirefox | ã¯ã | 1,5 | 1,5 | 1,5 | 1.3 |
ãã¹ã¯ãããããšããž | ãã | 23.1 | 20.6 | 18.1 | 13.0 |
ãã¹ã¯ãããããšããž | ã¯ã | 2.9 | 2.9 | 2.9 | 2,8 |
ã¢ãã€ã«ãChrome | ãã | 37.1 | 35.0 | 34.5 | 24.9 |
ã¢ãã€ã«ãChrome | ã¯ã | 5.2 | 5,6 | 5.3 | 4.7 |
ãã®å Žåããªã¹ããåå²ãããã°ã«ãŒãã«ã¯ç¬èªã®shouldComponentUpdateã¡ãœãããå®è£ ãããŠããããããã¹ãããã³ã³ããŒãã³ãã®ã¿ã€ãã¯éèŠã§ã¯ãããŸããã
ã¬ã³ããªã³ã°ã§æ°ããé¢æ°ãäœæããªãããã«ããæ¹æ³
å®éã«ã¯ãã»ãšãã©ã®å Žåãæ°ããã³ã³ããŒãã³ãããããã£ã®äžå¿ èŠãªçæã¯ãç¢å°é¢æ°ãŸãã¯ãã€ã³ãé¢æ°ã®äœ¿çšã«ãããã®ã§ãã ãã®åé¡ã解決ããæ¹æ³ãæ€èšããŠãã ããã ã»ãšãã©ã®å Žåãããã¯éåžžã«ç°¡åã§ãã ããããæã«ã¯æéãããããŸãã
æŽæ°ããšã«æ°ããé¢æ°ãäœæããªãæãç°¡åãªæ¹æ³ã¯ãã³ã³ããŒãã³ãã€ã³ã¹ã¿ã³ã¹ãåæåããããšãã«äžåºŠäœæããããšã§ãã
ãããè¡ãã«ã¯ãrenderã¡ãœããã§ã¯ãªãã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§bindé¢æ°ãåŒã³åºããåŸã§renderã¡ãœããã§åç §ããããã«ãçµæããªããžã§ã¯ãã®ããããã£ã«ä¿åããŸãã
ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã®ãã€ã³ãã®äŸïŒ
class ParentComponent extends React.Component { constructor(props) { super(props); this._onClick = this._onClick.bind(this); } _onClick() { doSomehing(); } render() { return <ChildComponent onClick={this._onClick}/>; } }
ãŸãã¯ãç¢å°é¢æ°ã䜿çšããŠãçµæããªããžã§ã¯ãã®ããããã£ã«ä¿åããããšãã§ããŸãã
ç¢å°é¢æ°ã䜿çšããäŸïŒ
class ParentComponent extends React.Component { _onClick = () => { doSomehing(); } render() { return <ChildComponent onClick={this._onClick}/>; } }
åã®æ¹æ³ã¯ãç°¡åãã€è¿ éã«å®è£ ã§ããŸãã ã»ãšãã©ã®å Žåã䜿çšãã䟡å€ããããŸãã
ãã ããã«ãŒãå ãªã©ãã³ãŒã«ããã¯é¢æ°ãåã³ã³ããŒãã³ãã®ãªã¹ãã«æž¡ãããå®è¡ããããšãã«ãåŒã³åºããçºçããèŠçŽ ãç¥ãå¿ èŠãããå ŽåããããŸãã ãã®ãããªé¢æ°ã¯ãããšãã°ãé åèŠçŽ ã®ã€ã³ããã¯ã¹ãåãããšãã§ããŸãã
ãªã¹ãã®äŸïŒ
class ParentComponent extends React.Component { _onClick = (index) => { doSomehing(index); } render() { return ( <div> {this.props.items.map((item, index) => ( <ChildComponent onClick={() => this._onClick(index)} item={item} /> ))} </div> ); } } class ChildComponent extends React.PureComponent { render() { return <div onClick={this.props.onClick}>...</div>; } }
ããã§ããªã¹ãã®ååã³ã³ããŒãã³ãã¯ãç¬èªã®äžæã®é¢æ°ãåãåãå¿ èŠããããŸãããã®é¢æ°ã§ã¯ãèŠçŽ ã®ã€ã³ããã¯ã¹ãã¯ããŒãžã£ãŒãéããŠä¿åãããŸãã
ãã®å Žåãåã¬ã³ããªã³ã°ã§æ°ããé¢æ°ã®äœæãåãé€ãããšã¯ããå°é£ã§ãã ãããè¡ãã«ã¯ããã€ãã®æ¹æ³ããããŸãã
åã³ã³ããŒãã³ãã®ã€ã³ã¿ãŒãã§ãŒã¹ãå€æŽãã
æåã®ã¢ãããŒããé©çšããã«ã¯ãã³ãŒã«ããã¯é¢æ°ã1ã€ã ãäœæããããããã¹ãŠã®åã³ã³ããŒãã³ãã«æž¡ãå¿ èŠããããŸãã ãã®å Žåãå¿ èŠãªåŒæ°ãé¢æ°ã«æž¡ã責任ã¯åã³ã³ããŒãã³ãã«ãããŸãã
idãæž¡ãäŸïŒ
class ParentComponent extends React.Component { _onClick = (id) => { doSomehing(id); } render() { return ( <div> {this.props.items.map((item) => ( <ChildComponent onClick={this._onClick} item={item} /> ))} </div> ); } } class ChildComponent extends React.PureComponent { _onClick = () => { this.props.onClick(this.props.item.id) } render() { return <div onClick={this._onClick}>...</div>; } }
åã³ã³ããŒãã³ãå ã«ã³ãŒã«ããã¯é¢æ°ã«å¿ èŠãªããŒã¿ããªãå Žåãããããã£ãä»ããŠåã³ã³ããŒãã³ãã«è»¢éããå¿ èŠããããŸãã
ããããã£ã«ã€ã³ããã¯ã¹ãè¿œå ããäŸïŒ
class ParentComponent extends React.Component { _onClick = (index) => { doSomehing(index); } render() { return ( <div> {this.props.items.map((item, index) => ( <ChildComponent onClick={this._onClick} item={item} index={index} /> ))} </div> ); } } class ChildComponent extends React.PureComponent { _onClick = () => { this.props.onClick(this.props.index) } render() { return <div onClick={this._onClick}>...</div>; } }
ãã®æ¹æ³ã¯åžžã«äœ¿çšã§ãããšã¯éããŸããã ãŸããåã³ã³ããŒãã³ãã®ãœãŒã¹ã³ãŒãã«ã¢ã¯ã»ã¹ã§ããªãå ŽåããããŸãã 第äºã«ãæ°ããããããã£ãè¿œå ããããšã¯ãã€ã³ã¿ãŒãã§ãŒã¹ã®æçããšæŽåæ§ã«æªåœ±é¿ãäžããå¯èœæ§ããããããæãŸãããªãå ŽåããããŸãã
ã³ã³ããŒãã³ãã®ãã€ã©ã€ã
åã®æ¹æ³ã䜿çšã§ããªãå ŽåããŸãã¯æãŸãããªãå Žåã¯ãã³ãŒã«ããã¯é¢æ°ã«è¿œå ã®ãã©ã¡ãŒã¿ãŒãæž¡ã責任ãããå¥ã®ã³ã³ããŒãã³ããäœæã§ããŸãã
ã³ã³ããŒãã³ãå²ãåœãŠã®äŸïŒ
class ParentComponent extends React.Component { _onClick = (index) => { doSomehing(index); } render() { return ( <div> {this.props.items.map((item, index) => ( <ChildWrapperComponent onClick={this._onClick} item={item} index={index} /> ))} </div> ); } } class ChildWrapperComponent extends React.PureComponent { _onClick = () => { this.props.onClick(this.props.index) } render() { return ( <ChildComponent onClick={this._onClick} item={item} /> ); } }
ãã®æ¹æ³ã¯ãã»ãšãã©ãã¹ãŠã®ç¶æ³ã§äœ¿çšã§ããŸãã ãããã圌ã®å¯äžã®æ¬ ç¹ã¯ããããæ¯èŒçé¢åã§ããããšã§ãã renderãåŒã³åºããšãã«é¢æ°ãäœæããã®ããããããã ãã«ãå¥ã®ã¯ã©ã¹ãæžãå¿ èŠããããŸãã
ããããã£ãšããŠå€ããã€ãã£ãèŠçŽ ã«æž¡ã
é åã€ã³ããã¯ã¹ïŒãŸãã¯ä»ã®ããŒïŒãåhtmlèŠçŽ ïŒãã¿ã³ãå ¥åãªã©ïŒã«è»¢éããã¡ãœããã䜿çšããããšãã§ããŸããã³ãŒã«ããã¯é¢æ°ã§ã€ãã³ããçºçãããšããã®ããŒã¿ã¯htmlèŠçŽ ããæœåºãããŸãã
htmlèŠçŽ ã䜿çšããäŸïŒ
class ParentComponent extends React.Component { _onClick = (e) => { doSomehing(e.target.value); } render() { return ( <div> {this.props.items.map((item, index) => ( <button type="button" onClick={this._onClick} value={index} > {item.title} </button> ))} </div> ); } }
htmlèŠçŽ ã®å ŽåãshouldComponentUpdateãå®è£ ã§ããŸãããããã¹ãã§ç€ºãããŠããããã«ãçµã¿èŸŒã¿ã®æé©åã¡ã«ããºã ããããããããã£ã®äžå€æ§ã«ããããã®ãããªèŠçŽ ã®æŽæ°æéãå€§å¹ ã«ççž®ãããŸãã
ã³ãŒã«ããã¯é¢æ°ã®ãã£ãã·ã¥
ãã®ã¡ãœããã䜿çšããã«ã¯ããã¹ãŠã®åã³ã³ããŒãã³ãã®ã³ãŒã«ããã¯é¢æ°ã®ãªã¹ããäžåºŠäœæãããã®åŸã®ã¬ã³ããªã³ã°ã«ä»¥åã«äœæããé¢æ°ã䜿çšããå¿ èŠããããŸãã ãã®ãããªå®è£ ã®ãªãã·ã§ã³ã®1ã€ïŒ
ã³ãŒã«ããã¯ãã£ãã·ã³ã°ïŒ
class ParentComponent extends React.Component { _callbacks = {}; _getOnClick = (index) => { if (!this._callbacks[index]) { this._callbacks[index] = () => doSomehing(index); } return this._callbacks[index]; } render() { return ( <div> {this.props.items.map((item, index) => ( <ChildComponent onClick={this._getOnClick(index)} item={item} /> ))} </div> ); } }
ãã®æ¹æ³ã¯æ¯èŒçæéãããããŸãã ã€ã³ããã¯ã¹ã«å ããŠãã³ãŒã«ããã¯é¢æ°ã«ä»ã®ããŒã¿ã転éããå¿ èŠãããå Žåããããæ£ããæ©èœããããã«ã¯ãããè€éãªããžãã¯ãå®è£ ããããå€ãã®ã³ãŒããèšè¿°ããå¿ èŠããããŸãã ããã«ããã®é¢æ°ã¯å¿ èŠã«å¿ããŠåã³ã³ããŒãã³ãã«ã³ããŒããå¿ èŠãããããã®ã³ãŒããåãã¯ã©ã¹ã«æ°ååã蟌ãããšãã§ããŸãã ãããã£ãŠãåã¯ã©ã¹ã®ã³ãŒãã®éè€ãé¿ããããã«ãå¿ èŠãªã¢ã¯ã·ã§ã³ãå®è¡ããã¢ãžã¥ãŒã«ãäœæã§ããŸãã
ãã®ãããªã¢ãžã¥ãŒã«ã®äŸãšããŠã2ã€ã®ããã±ãŒãžããããŸãã
- ãã£ãã·ã¥ãã€ã³ã
- åå¿ãã£ãã·ã¥ã³ãŒã«ããã¯
ã©ã¡ãã®ããã±ãŒãžã«ãåãæ©èœããããŸãããã€ã³ã¿ãŒãã§ãŒã¹ã¯ç°ãªããŸãã
ãããã䜿çšãããšããªã¹ãããååã³ã³ããŒãã³ãã®ã³ãŒã«ããã¯é¢æ°ãäžåºŠäœæããããã以éã®ã¬ã³ããªã³ã°ããšã«äœ¿çšã§ããŸãã
cached-bindã®äœ¿çšäŸïŒ
import bind from 'cached-bind'; class ParentComponent extends React.Component { _onClick(index) { doSomehing(index); } render() { return ( <div> {this.props.items.map((item, index) => ( <ChildComponent onClick={bind(this, '_onClick', index)} item={item} /> ))} </div> ); } }
React-cached-callbackã®äŸïŒ
import cached from 'react-cached-callback'; class ParentComponent extends React.Component { @cached _getOnClick(index) { return () => doSomehing(index); } render() { return ( <div> {this.props.items.map((item, index) => ( <ChildComponent onClick={this._getOnClick(index)} item={item} /> ))} </div> ); } }
ã©ã®ã¹ãã¢ãé¢æ°ãè¿ãå¿ èŠãããããç解ããã«ã¯ãäž¡æ¹ã®ããã±ãŒãžãåŒã³åºããããšãã«åã³ã³ããŒãã³ãã®èå¥åã決å®ããå¿ èŠããããŸãã èå¥åãšããŠãããšãã°ãé åå ã®èŠçŽ ã®ã€ã³ããã¯ã¹ã䜿çšã§ããŸãã
cached-bindã¯ããã€ã³ãé¢æ°ãåŒã³åºããšãã«ããã®èå¥åã3çªç®ã®åŒæ°ãšããŠåãåãå¿
èŠããããŸãã
ãŸããreact-cached-callbackã¯ããã©ã«ãã§ãå
ã®é¢æ°ã«æž¡ãããæåã®åŒæ°ãèå¥åãšèŠãªããŸãã ã€ã³ã¿ãŒãã§ãŒã¹ã®è©³çŽ°ã¯ãããã±ãŒãžã®èª¬æã«èšèŒãããŠããŸãã
çµè«ãšããŠ
Reactã¯é«éãªãã¬ãŒã ã¯ãŒã¯ã§ãããã¢ããªã±ãŒã·ã§ã³ã®å€§éšåã¯è¿œå ã®åŽåãªãã§ååãªããã©ãŒãã³ã¹ã§åäœããŸãã ãã ããã¢ããªã±ãŒã·ã§ã³ã®ãµã€ãºã倧ãããªããšãéçºè ã¯ããŸããŸãªæé©åææ³ãé©çšããã³ã³ããŒãã³ãã®ããããã£ãäžå¿ èŠã«å€æŽãããªãããã«ããå¿ èŠããããŸãã
çŸåšãå€ãã®ç¶æ 管çã©ã€ãã©ãªïŒreduxãMobXãªã©ïŒã«ã¯ãåå¿ã³ã³ããŒãã³ããæé©åããç¬èªã®æ¹æ³ããããŸãã ãã ããã³ã³ããŒãã³ãã䜿çšããå Žåã§ããã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãããšãã«ãªãã·ã§ã³ã§æ°ãããªããžã§ã¯ããšé¢æ°ãçæãããšããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®æŽæ°ãå€§å¹ ã«é ããããšããããŸãã