æè¿ã
JavaScriptãåŠã¶äººã察象ãšã
ãJavaScriptã®é«é颿°ã«é¢ããè³æãå
¬éããŸããã æ¬æ¥ç¿»èš³ããŠããèšäºã¯ãåå¿è
ã®Reactéçºè
ã察象ãšããŠããŸãã 髿¬¡ã³ã³ããŒãã³ãïŒHOCïŒã«çŠç¹ãåœãŠãŠããŸãã

Reactã®DRYååãšé«æ¬¡ã³ã³ããŒãã³ã
ããã°ã©ãã³ã°ã®ç ç©¶ãååã«é²ããããšã¯ã§ãããã»ãšãã©ã«ã«ãçãªDRYã®ååã«åºãããããšã¯ãããŸããïŒç¹°ãè¿ããªãã§ãã ãããç¹°ãè¿ããªãã§ãã ããïŒã æã
圌ã®ä¿¡è
ã¯è¡ãéããŸãããã»ãšãã©ã®å Žåããããå®ãããã«åªåãã䟡å€ããããŸãã ããã§ã¯ãDRYååãžã®æºæ ãä¿èšŒããæãäžè¬çãªReactéçºãã¿ãŒã³ã«ã€ããŠèª¬æããŸãã ããã¯ã髿¬¡ã®ã³ã³ããŒãã³ãã«é¢ãããã®ã§ãã 髿¬¡ã³ã³ããŒãã³ãã®äŸ¡å€ãçè§£ããããã«ãæåã«ããããæå³ããåé¡ãå®åŒåããŠçè§£ããŸãããã
ã¹ãã©ã€ãããã«ã«äŒŒãã³ã³ãããŒã«ããã«ãåäœæããå¿
èŠããããšããŸãã å€ãã®ãããžã§ã¯ãã«ã¯ããããžã§ã¯ããå®äºããç¬éãŸã§ãã¹ãŠãããŸãããå Žåãã¹ããŒã ã«åŸã£ãŠéçºããç¹æ§ããããŸãã äœæ¥ãã»ãŒçµäºãããšæããšãã³ã³ãããŒã«ããã«ã«ã¯ãç¹å®ã®èŠçŽ ã«ã«ãŒãœã«ãåããããšè¡šç€ºãããããŸããŸãªããŒã«ãããããããŸãã
ã³ã³ãããŒã«ããã«ãšããŒã«ããããã®ãããªæ©èœãå®è£
ããã«ã¯ãããã€ãã®ã¢ãããŒãã䜿çšã§ããŸãã ãããè¡ãããšã«ããŸããããã€ã³ã¿ãŒãåã
ã®ã³ã³ããŒãã³ãã®äžã«ãããã©ããã倿ããŠããããã®ãã³ãã衚瀺ãããã©ãããæ±ºå®ããŸãã åæ§ã®æ©èœãè£
åããå¿
èŠããã3ã€ã®ã³ã³ããŒãã³ãããããŸãã ãããã¯
Info
ã
TrendChart
ããã³
DailyChart
ã§ãã
Info
ã³ã³ããŒãã³ãããå§ããŸãããã ä»ã¯ã·ã³ãã«ãªSVGã¢ã€ã³ã³ã§ãã
class Info extends React.Component { render() { return ( <svg className="Icon-svg Icon--hoverable-svg" height={this.props.height} viewBox="0 0 16 16" width="16"> <path d="M9 8a1 1 0 0 0-1-1H5.5a1 1 0 1 0 0 2H7v4a1 1 0 0 0 2 0zM4 0h8a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm4 5.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" /> </svg> ) } }
次ã«ããã®ã³ã³ããŒãã³ãã§ããŠã¹ãã€ã³ã¿ãŒããã®äžã«ãããã©ããã倿ã§ããããã«ããå¿
èŠããããŸãã ããã«ã¯ã
onMouseOver
ããã³
onMouseOut
ããŠã¹ã€ãã³ãã䜿çšã§ããŸãã
onMouseOver
æž¡ããã颿°ã¯ãããŠã¹ãã€ã³ã¿ãŒãã³ã³ããŒãã³ãé åã«èœã¡ãå Žåã«åŒã³åºããã
onMouseOut
æž¡ããã颿°ã¯ããã€ã³ã¿ãŒãã³ã³ããŒãã³ãããé¢ãããšãã«åŒã³åºãããŸãã ããããã¹ãŠReactã§åãå
¥ããããããã«æŽçããããã«ãã¹ããŒãã«ä¿åãããŠããã³ã³ããŒãã³ãã«
hovering
ããããã£ã远å ããŸããããã«ããããã®ããããã£ã倿Žãããå Žåã«ããŒã«ãããã衚瀺ãŸãã¯é衚瀺ã«ããŠã³ã³ããŒãã³ããåã¬ã³ããªã³ã°ã§ããŸãã
class Info extends React.Component { state = { hovering: false } mouseOver = () => this.setState({ hovering: true }) mouseOut = () => this.setState({ hovering: false }) render() { return ( <> {this.state.hovering === true ? <Tooltip id={this.props.id} /> : null} <svg onMouseOver={this.mouseOver} onMouseOut={this.mouseOut} className="Icon-svg Icon--hoverable-svg" height={this.props.height} viewBox="0 0 16 16" width="16"> <path d="M9 8a1 1 0 0 0-1-1H5.5a1 1 0 1 0 0 2H7v4a1 1 0 0 0 2 0zM4 0h8a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm4 5.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" /> </svg> </> ) } }
ããªãããŸããããŸããã æ¬¡ã«ãåãæ©èœã
TrendChart
ãš
DailyChart
2ã€ã®ã³ã³ããŒãã³ãã«è¿œå ããå¿
èŠããã
DailyChart
ã
Info
ã³ã³ããŒãã³ãã®äžèšã®ã¡ã«ããºã ã¯æ£åžžã«æ©èœããå£ããŠããªããã®ã¯ä¿®åŸ©ããå¿
èŠããªããããåãã³ãŒãã䜿çšããŠä»ã®ã³ã³ããŒãã³ãã§åããã®ãåäœæããŸãããã
TrendChart
ã³ã³ããŒãã³ãã®ã³ãŒãããªãµã€ã¯ã«ããŸãã
class TrendChart extends React.Component { state = { hovering: false } mouseOver = () => this.setState({ hovering: true }) mouseOut = () => this.setState({ hovering: false }) render() { return ( <> {this.state.hovering === true ? <Tooltip id={this.props.id}/> : null} <Chart type='trend' onMouseOver={this.mouseOver} onMouseOut={this.mouseOut} /> </> ) } }
ããããæ¬¡ã«äœããã¹ããããã§ã«çè§£ããŠããã§ãããã æåŸã®ã³ã³ããŒãã³ãã§ãã
DailyChart
ã§ãåãããšãã§ããŸãã
class DailyChart extends React.Component { state = { hovering: false } mouseOver = () => this.setState({ hovering: true }) mouseOut = () => this.setState({ hovering: false }) render() { return ( <> {this.state.hovering === true ? <Tooltip id={this.props.id}/> : null} <Chart type='daily' onMouseOver={this.mouseOver} onMouseOut={this.mouseOut} /> </> ) } }
ããã§ãã¹ãŠæºåãæŽããŸããã Reactã§äŒŒããããªãã®ããã§ã«æžããŠãããããããŸããã ãã¡ãããããã¯äžçã§ææªã®ã³ãŒãã§ã¯ãããŸããããDRYã®ååã«ç¹ã«ããåŸã£ãŠããŸããã ã芧ã®ãšãããã³ã³ããŒãã³ãã³ãŒããåæããããšã«ãããããããã§åãããžãã¯ãç¹°ãè¿ããŸãã
ä»ç§ãã¡ãçŽé¢ããŠããåé¡ã¯éåžžã«æç¢ºã«ãªãã¯ãã§ãã ããã¯éè€ããã³ãŒãã§ãã ããã解決ããããã«ããã§ã«å®è£
æžã¿ã®ãã®ãæ°ããã³ã³ããŒãã³ãã«å¿
èŠãªå Žåã«åãã³ãŒããã³ããŒããå¿
èŠæ§ãåãé€ãããã§ãã è§£æ±ºæ¹æ³ ããã«ã€ããŠè©±ãåã«ãããã§ææ¡ãããœãªã¥ãŒã·ã§ã³ã®çè§£ã倧ãã«ä¿é²ããããã€ãã®ããã°ã©ãã³ã°ã®æŠå¿µã«ã€ããŠèª¬æããŸãã ã³ãŒã«ããã¯ãšé«é颿°ã«ã€ããŠè©±ããŠããŸãã
é«é颿°
JavaScriptã®é¢æ°ã¯ããã¡ãŒã¹ãã¯ã©ã¹ãªããžã§ã¯ãã§ãã ã€ãŸãããªããžã§ã¯ããé
åããŸãã¯æååã®ããã«ã倿°ã«å²ãåœãŠãããåŒæ°ãšããŠé¢æ°ã«æž¡ããããä»ã®é¢æ°ããè¿ããããããããšãã§ããŸãã
function add (x, y) { return x + y } function addFive (x, addReference) { return addReference(x, 5) } addFive(10, add)
ãã®åäœã«æ
£ããŠããªãå Žåãäžèšã®ã³ãŒãã¯å¥åŠã«èŠãããããããŸããã ããã§äœãèµ·ãã£ãŠããã®ã話ããŸãããã ã€ãŸãã
add
颿°ãåŒæ°ãšããŠ
addFive
颿°ã«
addReference
ãååã
addReference
ã«å€æŽããŠåŒã³åºããŸãã
ãã®ãããªæ§é ã䜿çšããå Žåãå¥ã®åŒæ°ãšããŠæž¡ããã颿°ã¯ã³ãŒã«ããã¯ïŒã³ãŒã«ããã¯é¢æ°ïŒãšåŒã°ããå¥ã®é¢æ°ãåŒæ°ãšããŠåãåã颿°ã¯é«é颿°ãšåŒã°ããŸãã
ããã°ã©ãã³ã°ã§ãšã³ãã£ãã£ã«ååãä»ããããšã¯éèŠã§ãããããã£ãŠãããã§ã¯ããšã³ãã£ãã£ãè¡šãæŠå¿µã«åŸã£ãŠååã倿Žãããã®ãšåãã³ãŒãã䜿çšããŸãã
function add (x,y) { return x + y } function higherOrderFunction (x, callback) { return callback(x, 5) } higherOrderFunction(10, add)
ãã®ãã¿ãŒã³ã¯ããªãã¿ã®ã¯ãã§ãã å®éãããšãã°JavaScripté
åã¡ãœããã䜿çšããŠjQueryãŸãã¯lodashãæäœããå Žåã¯ããã§ã«é«é颿°ãšã³ãŒã«ããã¯ã䜿çšããŠããŸãã
[1,2,3].map((i) => i + 5) _.filter([1,2,3,4], (n) => n % 2 === 0 ); $('#btn').on('click', () => console.log('Callbacks are everywhere') )
äŸã«æ»ããŸãããã
addFive
颿°ãäœæããã ãã§ãªãã
addTen
颿°ã
addTwenty
ãªã©ãäœæãããå Žåã¯
addTwenty
ã
addFive
颿°ã®
addFive
æ¹æ³ãèãããšãã³ãŒããã³ããŒããŠå€æŽããããã«åºã¥ããŠäžèšã®é¢æ°ãäœæããå¿
èŠããããŸãã
function add (x, y) { return x + y } function addFive (x, addReference) { return addReference(x, 5) } function addTen (x, addReference) { return addReference(x, 10) } function addTwenty (x, addReference) { return addReference(x, 20) } addFive(10, add)
ç§ãã¡ã®ã³ãŒãã¯ããã»ã©æªå€¢ã§ã¯ãªãã£ããããã®äžã®å€ãã®æçãç¹°ãè¿ãããŠããããšã¯æããã§ãã ç§ãã¡ã®ç®æšã¯ãã³ãŒãã®éè€ãæå°éã«æããªãããæž¡ãããæ°åã«ç¹å®ã®æ°åã远å ãã颿°ïŒ
addFive
ã
addTen
ã
addTwenty
ãªã©ïŒãå¿
èŠãªã ãäœæã§ããããšã§ãã ãããéæããããã«ã
makeAdder
颿°ãäœæããå¿
èŠããããŸããïŒ ãã®é¢æ°ã¯ãç¹å®ã®çªå·ãš
add
颿°ãžã®ãªã³ã¯ãåãããšã
add
ãŸãã ãã®é¢æ°ã®ç®çã¯ãæž¡ãããæ°å€ãæå®ãããæ°å€ã«è¿œå ããæ°ãã颿°ãäœæããããšãªã®ã§ãç¹å®ã®æ°å€ïŒ
makeFive
ã®æ°å€5ãªã©ïŒãå«ãæ°ãã颿°ã
makeAdder
颿°ããè¿ãããšãã§ããŸãããã®çªå·ã«è¿œå ããŸãã
äžèšã®ã¡ã«ããºã ã®å®è£
äŸãèŠãŠã¿ãŸãããã
function add (x, y) { return x + y } function makeAdder (x, addReference) { return function (y) { return addReference(x, y) } } const addFive = makeAdder(5, add) const addTen = makeAdder(10, add) const addTwenty = makeAdder(20, add) addFive(10)
ããã§ãã³ãŒãã®éè€ãæå°éã«æããªãããå¿
èŠãªæ°ã®
add
颿°ãäœæã§ããŸãã
è峿·±ãå Žåãä»ã®é¢æ°ãåŠçããŠç¹å®ã®é¢æ°ã䜿çšãã以åãããå°ãªããã©ã¡ãŒã¿ãŒã§äœ¿çšã§ããããã«ãããšããæŠå¿µã¯ãã颿°ã®éšåé©çšããšåŒã°ããŸãã ãã®ã¢ãããŒãã¯ã颿°åããã°ã©ãã³ã°ã§äœ¿çšãããŸãã ãã®äœ¿çšäŸã¯ãJavaScriptã§äœ¿çšããã
.bind
ã¡ãœããã§ãã
ããã¯ãã¹ãŠè¯ãããšã§ããããã®æ©èœãå¿
èŠãšããæ°ããã³ã³ããŒãã³ããäœæãããšãã«ãããŠã¹ã€ãã³ããåŠçããããã®ã³ãŒããè€è£œãããšããäžèšã®åé¡ãšReactã¯ã©ãé¢ä¿ããŸããïŒ äºå®ã¯ã髿¬¡é¢æ°
makeAdder
ãã³ãŒãã®éè€ãæå°éã«æããã®ãšåãããã«ãã髿¬¡ã³ã³ããŒãã³ãããšåŒã°ãããã®ããReactã¢ããªã±ãŒã·ã§ã³ã§åãåé¡ã«å¯ŸåŠããã®ã«åœ¹ç«ã€ãšããããšã§ãã ãã ããããã§ã¯ãã¹ãŠãå°ãç°ãªããŸãã ã€ãŸãã髿¬¡é¢æ°ãã³ãŒã«ããã¯ãåŒã³åºãæ°ãã颿°ãè¿ãäœæ¥ã¹ããŒã ã®ä»£ããã«ã髿¬¡ã³ã³ããŒãã³ããç¬èªã®ã¹ããŒã ãå®è£
ã§ããŸãã ã€ãŸããã³ãŒã«ããã¯ã®åœ¹å²ãæããã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããæ°ããã³ã³ããŒãã³ããè¿ãããšãã§ããŸãã ããããç§ãã¡ã¯ãã§ã«å€ãã®ããšãèšã£ãŠããã®ã§ãäŸã«ç§»ãæéã§ãã
æé«æ¬¡æ©èœ
ãã®æ©èœã«ã¯æ¬¡ã®æ©èœããããŸãã
- åœŒå¥³ã¯æ©èœã§ãã
- 圌女ã¯åŒæ°ãšããŠã³ãŒã«ããã¯ãåãå
¥ããŸãã
- æ°ãã颿°ãè¿ããŸãã
- è¿ããã颿°ã¯ãé«é颿°ã«æž¡ãããå
ã®ã³ãŒã«ããã¯ãåŒã³åºãããšãã§ããŸãã
function higherOrderFunction (callback) { return function () { return callback() } }
æé«äœã®ã³ã³ããŒãã³ã
ãã®ã³ã³ããŒãã³ãã¯ã次ã®ããã«ç¹åŸŽä»ããããšãã§ããŸãã
- ããã¯ã³ã³ããŒãã³ãã§ãã
- åŒæ°ãšããŠãå¥ã®ã³ã³ããŒãã³ããåããŸãã
- æ°ããã³ã³ããŒãã³ããè¿ããŸãã
- è¿ãããã³ã³ããŒãã³ãã¯ã髿¬¡ã³ã³ããŒãã³ãã«æž¡ãããå
ã®ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ã§ããŸãã
function higherOrderComponent (Component) { return class extends React.Component { render() { return <Component /> } } }
HOCã®å®è£
äžè¬çã«ã¯ã髿¬¡ã³ã³ããŒãã³ããå®è¡ããã¢ã¯ã·ã§ã³ãæ£ç¢ºã«ææ¡ããã®ã§ãReactã³ãŒãã«å€æŽãå ãå§ããŸãã èŠããŠãããªããç§ãã¡ã解決ããããšããŠããåé¡ã®æ¬è³ªã¯ãããŠã¹ã€ãã³ããåŠçããããžãã¯ãå®è£
ããã³ãŒããããã®æ©èœãå¿
èŠãšãããã¹ãŠã®ã³ã³ããŒãã³ãã«ã³ããŒããå¿
èŠããããšããããšã§ãã
state = { hovering: false } mouseOver = () => this.setState({ hovering: true }) mouseOut = () => this.setState({ hovering: false })
ãããèãããšãããŠã¹ã€ãã³ãåŠçã³ãŒããã«ãã»ã«åããã¬ã³ããªã³ã°ããã³ã³ããŒãã³ãã«
hovering
ããããã£ãæž¡ãããã«ã髿¬¡ã³ã³ããŒãã³ãïŒ
withHover
åŒã³åºããŸãããïŒãå¿
èŠã§ãã ããã«ããã
withHover
ã³ã³ããŒãã³ãã«é
眮ããããšã§ã察å¿ããã³ãŒãã®éè€ãé²ãããšãã§ããŸãã
æçµçã«ããããç§ãã¡ãéæãããããšã§ãã
hovering
ããããã£ãææ¡ããå¿
èŠãããã³ã³ããŒãã³ããå¿
èŠãªå Žåã¯ããã®ã³ã³ããŒãã³ãã髿¬¡ã³ã³ããŒãã³ã
withHover
æž¡ãããšãã§ããŸãã ã€ãŸããæ¬¡ã®ããã«ã³ã³ããŒãã³ããæäœããå¿
èŠããããŸãã
const InfoWithHover = withHover(Info) const TrendChartWithHover = withHover(TrendChart) const DailyChartWithHover = withHover(DailyChart)
次ã«ã
withHover
ãã¬ã³ããªã³ã°ããããšã
hovering
ããããã£ãæž¡ãããå
ã®ã³ã³ããŒãã³ãã«ãªããŸãã
function Info ({ hovering, height }) { return ( <> {hovering === true ? <Tooltip id={this.props.id} /> : null} <svg className="Icon-svg Icon--hoverable-svg" height={height} viewBox="0 0 16 16" width="16"> <path d="M9 8a1 1 0 0 0-1-1H5.5a1 1 0 1 0 0 2H7v4a1 1 0 0 0 2 0zM4 0h8a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm4 5.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" /> </svg> </> ) }
å®éã®ãšãããä»ã¯
withHover
ã³ã³ããŒãã³ããå®è£
ãã
withHover
ã§ãã äžèšããã3ã€ã®ã¢ã¯ã·ã§ã³ãå®è¡ããå¿
èŠãããããšãçè§£ã§ããŸãã
- ã³ã³ããŒãã³ãåŒæ°ãåãå
¥ããŸãã
- æ°ããã³ã³ããŒãã³ããè¿ããŸãã
hovering
ããããã£ãæž¡ãããšã«ãããã³ã³ããŒãã³ãåŒæ°ãã¬ã³ããªã³ã°ããŸãã
Componentã³ã³ããŒãã³ãåŒæ°ã®åãå
¥ã
function withHover (Component) { }
newæ°ããã³ã³ããŒãã³ããè¿ã
function withHover (Component) { return class WithHover extends React.Component { } }
Componentãããªã³ã°ããããã£ãæž¡ãããšã«ããã³ã³ããŒãã³ãã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°
ä»ãç§ãã¡ã¯æ¬¡ã®è³ªåã«çŽé¢ããŠããŸãïŒ
hovering
ããããã£ã«å°éããæ¹æ³ïŒ å®éããã®ããããã£ãæäœããããã®ã³ãŒãã¯ãã§ã«äœæãããŠããŸãã æ°ããã³ã³ããŒãã³ãã«è¿œå ããã ãã§ã
Component
åŒæ°ã®åœ¢åŒã§é«æ¬¡ã³ã³ããŒãã³ãã«æž¡ãããã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãããšãã«
hovering
ããããã£ãæž¡ãã ãã§ãã
function withHover(Component) { return class WithHover extends React.Component { state = { hovering: false } mouseOver = () => this.setState({ hovering: true }) mouseOut = () => this.setState({ hovering: false }) render() { return ( <div onMouseOver={this.mouseOver} onMouseOut={this.mouseOut}> <Component hovering={this.state.hovering} /> </div> ); } } }
ãããã®ããšã«ã€ããŠã¯ãïŒReactã®ããã¥ã¡ã³ãã«ããããã«ïŒæ¬¡ã®æ¹æ³ã§è©±ãããšã奜ã¿ãŸããã³ã³ããŒãã³ãã¯ããããã£ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã«å€æãã髿¬¡ã³ã³ããŒãã³ãã¯ã³ã³ããŒãã³ããå¥ã®ã³ã³ããŒãã³ãã«å€æããŸãã ãã®å Žåã
Info
ã
TrendChart
ããã³
DailyChart
ã³ã³ããŒãã³ããã
hovering
ããããã£ã®ãããã§ãããŠã¹ãã€ã³ã¿ãŒããããã®äžã«ãããã©ãããç¥ãæ°ããã³ã³ããŒãã³ãã«å€æããŸãã
远å ã®ã¡ã¢
ãã®æç¹ã§ã髿¬¡ã³ã³ããŒãã³ãã«é¢ãããã¹ãŠã®åºæ¬æ
å ±ã確èªããŸããã ãã ããè°è«ãã¹ãéèŠãªããšãããã€ããããŸãã
HOCã§HOCãèŠããšãå°ãªããšã1ã€ã®åŒ±ç¹ãããããšã
withHover
ãŸãã
hovering
ããããã£ã®ã¬ã·ãŒããŒã³ã³ããŒãã³ãã¯ããã®ããããã£ã§åé¡ãçºçããªãããšãæå³ããŸãã ã»ãšãã©ã®å Žåããã®ä»®å®ã¯æ£åœåãããå¯èœæ§ãé«ãã§ãããããã¯åãå
¥ããããªãããšãèµ·ãããããããŸããã ããšãã°ãã³ã³ããŒãã³ãã«æ¢ã«
hovering
ããããã£ãããå Žåã¯ã©ããªããŸããïŒ ãã®å Žåãååã®è¡çªãçºçããŸãã ãããã£ãŠã
withHover
ã³ã³ããŒãã³ãã«
withHover
ããšãã§ããŸããããã«ããããã®ã³ã³ããŒãã³ãã®ãŠãŒã¶ãŒã¯ã
hovering
ããããã£ãã³ã³ããŒãã³ãã«æž¡ãååãæå®ã§ããããã«ãªããŸãã
withHover
ã¯åãªã颿°ã§ãããããã³ã³ããŒãã³ãã«æž¡ãããããããã£ã®ååãèšå®
withHover
2çªç®ã®åŒæ°ã
withHover
ããã«æžãæããŸãããã
function withHover(Component, propName = 'hovering') { return class WithHover extends React.Component { state = { hovering: false } mouseOver = () => this.setState({ hovering: true }) mouseOut = () => this.setState({ hovering: false }) render() { const props = { [propName]: this.state.hovering } return ( <div onMouseOver={this.mouseOver} onMouseOut={this.mouseOut}> <Component {...props} /> </div> ); } } }
ES6ã®ããã©ã«ãã®ãã©ã¡ãŒã¿ãŒã¡ã«ããºã ã®ãããã§ã2çªç®ã®åŒæ°ã®æšæºå€ã
hovering
ãšããŠèšå®ããŸããã
withHover
ã³ã³ããŒãã³ãã®ãŠãŒã¶ãŒãããã倿Žãããå Žåããã®2çªç®ã®åŒæ°ã«å¿
èŠãªååãæž¡ãããšãã§ããŸãã
function withHover(Component, propName = 'hovering') { return class WithHover extends React.Component { state = { hovering: false } mouseOver = () => this.setState({ hovering: true }) mouseOut = () => this.setState({ hovering: false }) render() { const props = { [propName]: this.state.hovering } return ( <div onMouseOver={this.mouseOver} onMouseOut={this.mouseOut}> <Component {...props} /> </div> ); } } } function Info ({ showTooltip, height }) { return ( <> {showTooltip === true ? <Tooltip id={this.props.id} /> : null} <svg className="Icon-svg Icon--hoverable-svg" height={height} viewBox="0 0 16 16" width="16"> <path d="M9 8a1 1 0 0 0-1-1H5.5a1 1 0 1 0 0 2H7v4a1 1 0 0 0 2 0zM4 0h8a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm4 5.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" /> </svg> </> ) } const InfoWithHover = withHover(Info, 'showTooltip')
ãããŒå®è£
ã®åé¡
withHover
ã®å®è£
ã«é¢ããå¥ã®åé¡ã«æ°ã¥ãããããããŸããã
Info
ã³ã³ããŒãã³ããåæãããšããšãããã
height
ããããã£ãåãå
¥ããŠããããšãããããŸãã ãã¹ãŠãé
眮ããæ¹æ³ã¯ã
height
ã
undefined
ã«èšå®
height
ããããšãæå³ããŸãã ããã¯ã
withHover
ã³ã³ããŒãã³ããã
Component
åŒæ°ãšããŠæž¡ããããã®ãã¬ã³ããªã³ã°ããã³ã³ããŒãã³ãã§ããããã§ãã ããã§ãäœæãã
hovering
以å€ã®ããããã£ã
Component
ã³ã³ããŒãã³ãã«è»¢éããŸããã
const InfoWithHover = withHover(Info) ... return <InfoWithHover height="16px" />
height
ããããã£ã¯
InfoWithHover
ã³ã³ããŒãã³ãã«æž¡ãããŸãã ãããŠããã®ã³ã³ããŒãã³ãã¯äœã§ããïŒ ããã¯
withHover
ããè¿ããã
withHover
ã§ãã
function withHover(Component, propName = 'hovering') { return class WithHover extends React.Component { state = { hovering: false } mouseOver = () => this.setState({ hovering: true }) mouseOut = () => this.setState({ hovering: false }) render() { console.log(this.props)
WithHover
ã³ã³ããŒãã³ãå
ã§ã¯
WithHover
this.props.height
ã¯
this.props.height
ã§ãããå°æ¥ãã®ããããã£ã§ã¯äœãããŸããã ãã®ããããã£ããã¬ã³ããªã³ã°ãã
Component
åŒæ°ã«æž¡ãå¿
èŠããããŸãã
render() { const props = { [propName]: this.state.hovering, ...this.props, } return ( <div onMouseOver={this.mouseOver} onMouseOut={this.mouseOut}> <Component {...props} /> </div> ); }
æäžäœã®ãµãŒãããŒãã£ã³ã³ããŒãã³ãã䜿çšããéã®åé¡ã«ã€ããŠ
åãã³ãŒããã³ããŒããããšãªããç°ãªãã³ã³ããŒãã³ãã§ããžãã¯ãåå©çšããéã«ã髿¬¡ã³ã³ããŒãã³ãã䜿çšããå©ç¹ããã§ã«çè§£ããŠãããšä¿¡ããŠããŸãã æ¬¡ã«ã髿¬¡ã®ã³ã³ããŒãã³ãã«æ¬ é¥ããããã©ããã確èªããŸãããã ãã®è³ªåã«ã¯ååãã«çããããšãã§ãããã§ã«ãããã®æ¬ ç¹ã«çŽé¢ããŠããŸãã
HOCã䜿çšãããšã
å¶åŸ¡ã®å転ãçºçããŸãã HOC
withRouter
React Routerãªã©ãåœç€Ÿãéçºãããã®ã§ã¯ãªã髿¬¡ã³ã³ããŒãã³ãã䜿çšããŠãããšæ³åããŠãã ããã ããã¥ã¡ã³ãã«ãããšã
withRouter
ã¯ã
match
ã
location
ã
history
ããããã£ããã¬ã³ããªã³ã°æã«ã©ããããã³ã³ããŒãã³ãã«æž¡ããŸãã
class Game extends React.Component { render() { const { match, location, history } = this.props
Game
èŠçŽ ïŒã€ãŸã-
<Game />
ïŒãäœæããŠããªãããšã«æ³šæããŠãã ããã React Routerã³ã³ããŒãã³ããå®å
šã«è»¢éãããã®ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããã ãã§ãªããã³ã³ããŒãã³ãã«æ£ããããããã£ãæž¡ãããšãä¿¡é ŒããŠããŸãã
hovering
ããããã£ãæž¡ããšãã«ååã®ç«¶åãçºçããå¯èœæ§ãããããšã説æããåã«ããã®åé¡ãæ¢ã«çºçããŠããŸãã ãããä¿®æ£ããããã«ãHOC
withHover
2çªç®ã®åŒæ°ã䜿çšããŠå¯Ÿå¿ããããããã£ã®ååãæ§æã§ããããã«ããããšã«ããŸããã ä»ã®èª°ãã®HOCã
withRouter
䜿çšãããšããã®ãããªæ©äŒã¯ãããŸããã
match
ã
location
ãŸãã¯
history
ããããã£ã
Game
ã³ã³ããŒãã³ãã§ãã§ã«äœ¿çšãããŠããå Žåãéãæªãã£ããšèšããŸãã ã€ãŸããã³ã³ããŒãã³ãã§ãããã®ååã倿ŽããããHOC
withRouter
䜿çšãæåŠããå¿
èŠããããŸãã
ãŸãšã
Reactã®HOCã«ã€ããŠèšãã°ãçæãã¹ã2ã€ã®éèŠãªããšããããŸãã ãŸããHOCã¯åãªããã¿ãŒã³ã§ãã 髿¬¡ã³ã³ããŒãã³ãã¯ãã¢ããªã±ãŒã·ã§ã³ã®ã¢ãŒããã¯ãã£ã«é¢é£ããŠãããšããäºå®ã«ãããããããReactã«åºæã®ãã®ãšåŒã¶ããšããã§ããŸããã 第äºã«ãReactã¢ããªã±ãŒã·ã§ã³ãéçºããããã«ã髿¬¡ã®ã³ã³ããŒãã³ãã«ã€ããŠç¥ãå¿
èŠã¯ãããŸããã ããªãã¯ãããã«äžæ
£ããããããŸããããåªããããã°ã©ã ãæžããŠãã ããã ãã ããä»ã®ããžãã¹ãšåæ§ã«ã䜿çšããããŒã«ãå€ããã°å€ãã»ã©ãäœæ¥ã®çµæã¯è¯ããªããŸãã ãŸããReactã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãäœæããå ŽåãHOCãå
µåšåº«ã«è¿œå ããããšãªããèªåèªèº«ã«æå®³ãäžããããšã«ãªããŸãã
芪æãªãèªè
ïŒ Reactã§é«æ¬¡ã®ã³ã³ããŒãã³ãã䜿çšããŠããŸããïŒ
