æ¥ãã 2 æ 4 æ¥ãã€ãã« React 16.8 ã®æ£åŒçããªãªãŒã¹ãããŸãããã® React 16.8 ã«ã¯ãã¢ã«ãã¡çãå ¬éãããŠä»¥æ¥åžžã« React ãŠãŒã¶ãŒãã¡ã®é¢å¿ãã»ãããŸãŸã«ããŠããReact Hooksãæ£åŒçãšãªã£ãŠè¿œå ãããŸãã
â»è¿œèšïŒã¢ã¡ãªã«æéã§ 2 æ 5 æ¥ã«ãªã£ãŠã React 16.8 ããªãªãŒã¹ãããŸããã§ãããäºåæ
å ±ã§ 2 æ 4 æ¥ãšèšã£ãŠãã®ã«âŠâŠããã€ã«ãªã£ãããªãªãŒã¹ãããã®ãã¯ããåãããŸããã2 æ 6 æ¥ã« React 16.8 ããªãªãŒã¹ãããŸããïŒ
ç±å¿ãª React ãŠãŒã¶ãŒã®æ¹ã¯ãåœç¶ React Hooks ã®æ å ±ãåžžã«è¿œã£ãŠããæ£åŒçããªãªãŒã¹ããããããã«ã§ãèªåã®ã³ãŒãã§äœ¿ãã¯ãããæºåãã§ããŠããããšãšæããŸãããããããã®èšäºããèŠ§ã®æ¹ã ã®äžã«ã¯ React ã䜿ã£ãŠããã«ãé¢ããããReact Hooks ã®ããšã¯ããåãããªãããšããèããããšãããã¯ãããã©ä»ã©ããªã£ãŠããã®ãç¥ããªãããšããæ£åŒçãåºãŠãã調ã¹ãã°ããããšæã£ãŠããããšããæ¹ãããããããå± ããããããŸããã
ããããæ£åŒçã®ç»å Žãšçžæã£ãŠããŸããŸãããããçããã¯ãã React Hooks ããéããããšã¯ã§ããŸãã1ããã®èšäºã§ã¯äžèšã®ãããªæ¹ã ã察象ãšããŠãReact Hooks ã®æ£åŒçã«åããŠã©ããªããã¯ãããã®ãããã¹ãŠèª¬æããŸããã¢ã«ãã¡çã®ãã¡ã¯ API ã®å€åããããŸãããããå°ãåã«ã¡ãã£ãšèª¿ã¹ãŠã¿ããã©ä»ã©ããªã£ãŠããã®ãã¯åãããªããšãããããªäººã¯èŠãã§ãã¯ã§ãããªããReact ã¯ããã¥ã¡ã³ãã®å å®ã«åãå ¥ããŠãããReact Hooks ã«é¢ããŠãå ¬åŒããã¥ã¡ã³ããã¡ãããšææ°ã®ç¶æ ã«ä¿ãããŠããŸããã§ããããè±èªãèªãã人ã¯ãã®èšäºãèªãŸãã«å ¬åŒããã¥ã¡ã³ããèªãã®ããããããããŸããã
èšäºäžã«ç»å Žãããµã³ãã«ã³ãŒãã¯GitHubã«çœ®ããŠãããŸãã
React Hooks ã®æŠèŠ
ç·ããããšããã¿ã€ãã«ãã€ããèšäºãªã®ã§ãäžå¿ React Hooks ã«ã€ããŠåºç€ãã説æããŠãããŸããReact Hooks ã¯ãäžèšã§èšãã°é¢æ°ã³ã³ããŒãã³ããã䜿ããæ°ãã APIã§ãããããŸã§ã颿°ã³ã³ããŒãã³ãã¯åŒæ°ãšã㊠props ãåãåããã¬ã³ããªã³ã°çµæãè¿ãå€ã§è¿ããšããã€ã³ã¿ãŒãã§ãŒã¹ã§å®çŸ©ãããã¹ããŒããªã©ã®è€éãªæ©èœãæããªãåçŽãªã³ã³ããŒãã³ããäœãããã®ãšããŠæäŸãããŠããŸãããåæã«ã¯ Stateless Function ComponentïŒç¶æ
ãªã颿°ã³ã³ããŒãã³ãïŒãšããçšèªã䜿ãããŠããããšãããåããéããããšããšé¢æ°ã³ã³ããŒãã³ãã¯ãã¯ã©ã¹ã³ã³ããŒãã³ããæã€ãããªstateã®æ©èœãcomponentDidMountãå§ããšããã©ã€ããµã€ã¯ã«ã¡ãœãããæã¡ãŸããã§ããã
React Hooks ã«ãã£ãŠã颿°ã³ã³ããŒãã³ãã«ãããã®æ©èœãæãããããšãã§ããããã«ãªããŸããããªãã¡ãåŸæ¥ã¯ã¯ã©ã¹ã³ã³ããŒãã³ãã§ããåºæ¥ãªãã£ãããšã颿°ã³ã³ããŒãã³ãã§ãã§ããããã«ãªãã®ã§ãããã äžã€æ³šæããŠããã ãããã®ã¯ãReact Hooks ã¯ã¯ã©ã¹ã³ã³ããŒãã³ãã® API ããã ç§»æ€ããããã§ã¯ãªããšããããšã§ããReact Hooks ã® API ã¯æ°ãããã¶ã€ã³ãçŽããã API ã§ãããåŸæ¥ã® API ã®åé¡ç¹ãè§£æ¶ãããŠããŸããäŸãã°ãããã¯ã®å©ç𿹿³ããã ã®é¢æ°åŒã³åºããšããããšã«ãã£ãŠãããã¯ã®åæïŒïŒã«ã¹ã¿ã ããã¯ã®äœæïŒã容æã«ããŠããŸãïŒã«ã¹ã¿ã ããã¯ã«ã€ããŠã¯çè ã®ä»¥åã®èšäºãåèã«ãªããããããŸããïŒã
React Hooks ã¯ãAPI äžã¯useããå§ãŸãååã®ãã ã®é¢æ°ã§ããreactããã±ãŒãžããuseStateãuseEffectãªã©ã®é¢æ°ããšã¯ã¹ããŒããããŠããŸããè£ã§ã¯ React ãä»ã©ã®ã³ã³ããŒãã³ããåŠçããŠããããšãã£ãæ
å ±ãä¿æããŠããããããã®é¢æ°ã¯ãã®æ
å ±ã«åºã¥ããŠé©åã«åäœããŸããçŸåšã®ãšãããReact Hooks ã® API ã¯é¢æ°ã³ã³ããŒãã³ãå°çšã§ããããã以å€ã®ã·ãã¥ãšãŒã·ã§ã³ã§åŒã³åºãããšã¯ã§ããŸããã
åºæ¬ã®ããã¯
å
è¿°ã®ããã¥ã¡ã³ãã§ã¯ãuseState, useEffect, useContextã® 3 ã€ãåºæ¬çãªããã¯ãšããŠæããããŠããŸããããã«å£ã£ãŠããã§ããŸãã¯ãã® 3 ã€ã玹ä»ããŸãã
useState
useStateããã¯ã¯ã颿°ã³ã³ããŒãã³ãã«ã¹ããŒããæããããã API ã§ãããã®ããã¯ã䜿ããšãã¯ã©ã¹ã³ã³ããŒãã³ãã«ãããthis.stateã«å€ãä¿åããŠããã®ãšåããããªæãã§ãã³ã³ããŒãã³ãã«ç¶æ
ãæãããããšãã§ããŸããäœ¿ãæ¹ã¯const [stateã®å€, stateæŽæ°é¢æ°] = useState(stateåæå€);ãšããã®ãåºæ¬ã§ãã
useState ã®ãµã³ãã«
ãã£ããã§ãããuseStateã®äœ¿çšäŸãèŠãŠã¿ãŸããããããããäŸã§ããããã¿ã³ãæŒããšæ°å€ãå¢ãããæžã£ãããããã€ã§ãã
import * as React from 'react';
const { useState } = React;
export const UseStateSample = () => {
const [count, setCount] = useState(0);
return (
<p>
<button onClick={() => setCount(count - 1)}>-</button>
<b>{count}</b>
<button onClick={() => setCount(count + 1)}>+</button>
</p>
);
};
ãã®useStateSampleã¯é¢æ°ã³ã³ããŒãã³ãã§ãç¹ã« props ãåãåããã« render å
容ãè¿ããšããåŸæ¥ã©ããã®ã€ã³ã¿ãŒãã§ãŒã¹ãæã£ãŠããŸãããã€ã³ãã¯ããã®åŠçã®äžã§useState颿°ãåŒã³åºããŠããç¹ã§ãã
ä»åã¯countãšããã¹ããŒããåæå€0ã§çšæããŠããŸãããã£ãŠã<b>{count}</b>ã®ãšããã¯æå㯠0 ã衚瀺ãããŸãã2 ã€ã®ãã¿ã³ãã¯ãªãã¯ãããšãsetCountãåŒã³åºãããããã«ãªã£ãŠããŸããsetCountãåŒã³åºããå Žåã¯æž¡ããåŒæ°ã§countã¹ããŒããæŽæ°ãããŸããã€ãŸããUseStateSampleã®årenderåŠçãçºçãããã®éuseStateã«ãã£ãŠè¿ãããcountã®å€ãæ°ããå€ãšãªã£ãŠããŸãã
ã¯ã©ã¹ã³ã³ããŒãã³ããšã®æ¯èŒ
äžã®ãµã³ãã«ãšåãåŠçãæ¢ããŠæ§æ¥ã®ã¯ã©ã¹ã³ã³ããŒãã³ãã§æžããšãããªæãã§ãã
export class UseStateSample extends React.Component {
state = { count: 0 };
render() {
const { count } = this.state;
return (
<p>
<button onClick={() => this.setState({ count: count - 1 })}>-</button>
<b>{count}</b>
<button onClick={() => this.setState({ count: count + 1 })}>+</button>
</p>
);
}
}
颿°ã³ã³ããŒãã³ããš Hooks ã§æžããå Žåã«æ¯ã¹ãŠç
©éã§ããããã®èŠå ãšããŠã¯ãã¯ã©ã¹ã³ã³ããŒãã³ãã§ã¯this.stateããªããžã§ã¯ãã§ããããšããthis.setStateããã®ãªããžã§ã¯ãã®ãã¡äžéšãã¢ããããŒããããã㪠API èšèšã«ãªã£ãŠããããšãæããããŸããReact Hooks ã® API ã§ã¯countãšããã¹ããŒãã«å¯ŸããŠsetCountãšããå°çšã®é¢æ°ãã»ããã§çšæãããŸãããã{count: count+1}ã®ãããªäœèšãªãªããžã§ã¯ãçæããªãçŽæçãã€ãã£ãããšæžãããšãã§ããŠããŸãã
è€æ°ã®ã¹ããŒãã䜿ã
颿°ã³ã³ããŒãã³ãã§ã¯ãuseStateãè€æ°ååŒã¶ããšã§è€æ°ã®ã¹ããŒããå©çšããããšãã§ããŸãããã®å Žåãããããã®ã¹ããŒãã«å¯ŸããŠå¥ã
ã®æŽæ°é¢æ°ãåŸãããŸãã
export const UseStateSample2 = () => {
const [left, setLeft] = useState(0);
const [right, setRight] = useState(0);
return (
<p>
<b>{left}</b>
<button
onClick={() => {
setLeft(left + 1);
setRight(right - 1);
}}
>
â
</button>
<b>{right}</b>
<button onClick={() => setRight(right + 1)}>+</button>
</p>
);
};
ãã®äŸã§ã¯ã³ã³ããŒãã³ãã¯leftãšrightãšãã 2 ã€ã®ã¹ããŒããæã£ãŠããŸããããããã®ã¹ããŒããã¢ããããŒãããã«ã¯å¯Ÿå¿ãã颿°ãçšããŸããçãäžãããã«èŠããããã«ãè€æ°ã®ã¹ããŒããåæã«æŽæ°ããã«ã¯é¢æ°ãå
šéšåŒã³ãŸãã
ãããèŠããšãã¹ããŒããè€éã«ãªã£ãŠãããšãã«ã¹ããŒãã®æŽæ°ãäžçºã§ã§ããã«ããããã®é¢æ°åŒã³åºããå¿
èŠã«ãªã£ãŠããŸããšããæžå¿µããããããããŸããããã®å Žåã¯ã¹ããŒãã®å€ãæ°å€ãªã©ã§ã¯ãªããªããžã§ã¯ãã«ããŠäžçºã§æŽæ°ããã»ããããããšããããŸãããã®ããæ¹ãæ¯æŽããããã¯ãšããŠuseReducerããããŸãã®ã§ãããšã§ç޹ä»ããŸãã
颿°ã«ããã¹ããŒãã®æŽæ°
ã¹ããŒãã®æŽæ°é¢æ°ïŒäžã®äŸã§ã®setCountãªã©ïŒãåŒã¶å Žåãä»ãŸã§ã®ãµã³ãã«ã§ã¯æ°ããã¹ããŒãã®å€ãæž¡ããŠããŸãããäžèšã®äŸã§ã¯ããã®ãã¿ã³ãæŒããšcountã¹ããŒãã 1 å¢ãããã€ãŸãæ°ããå€ãšããŠcount + 1ãã»ããããŠããããšãåãããŸãã
<button onClick={() => setCount(count + 1)}>+</button>
å®ã¯ãæŽæ°é¢æ°ã«ã¯é¢æ°ãæž¡ãããšãã§ããŸãããã®å Žåãããã¯çŸåšã®ã¹ããŒãã®å€ãåãåã£ãŠæ°ããã¹ããŒãã®å€ãè¿ã颿°ãšããŠè§£éãããŸããã€ãŸããäžã®äŸã¯ãã®ããã«æžãæããããšãã§ããŸãã
<button onClick={() => setCount(count => count + 1)}>+</button>
ããã¯setCountã«é¢æ°ãæž¡ãããšã§ããçŸåšã®ã¹ããŒããèªãã§ãããã« 1 ãè¶³ããå€ãæ°ããã¹ããŒãã®å€ãšããããšããããšãæç€ºããŠããŸãããã®ããã«ã次ã®ã¹ããŒãã®å€ãçŸåšã®ã¹ããŒãã«äŸåããå ŽåïŒããªãã¡çŸåšã®ã¹ããŒãããæ°ããã¹ããŒããèšç®ããå ŽåïŒã¯é¢æ°ãçšããæŽæ°ãé©ããŠããŸãã
ãã®çç±ã® 1 ã€ã¯ããã®æ¹æ³ã ãšã¹ããŒãã®æŽæ°ããžãã¯ãçŽç²é¢æ°ã«æãåºãããšãã§ããããšã§ããããã«ãã 1 ã€ã®çç±ãšããŠã颿°ã䜿ããªããšã³ãŒã«ããã¯ãè€æ°ååŒã°ããå Žåã«æ£ãã察åŠã§ããªãããšããããŸãã
äŸãšããŠãã1 åæŒããš onClick ã 5 åçºçãããã¿ã³ããšããã³ã³ããŒãã³ãSuperButtonãäœã£ãŠã¿ãŸããããã®ãã¿ã³ã䜿ããš 2 ã€ã®æ¹æ³ã®éããåãããŸãã
const SuperButton = ({ onClick, children }) => {
const onclickHere =
onClick &&
(e => {
for (const _ of [0, 1, 2, 3, 4]) onClick(e);
});
return <button onClick={onclickHere}>{children}</button>;
};
export const UseStateSample4 = () => {
const [count, setCount] = useState(0);
return (
<p>
<SuperButton onClick={() => setCount(count - 1)}>-</SuperButton>
<b>{count}</b>
<SuperButton onClick={() => setCount(count => count + 1)}>+</SuperButton>
</p>
);
};
ãã®äŸã§ã¯ãSuperButtonã® onClick 颿°ã§ 2 çš®é¡ã®æ¹æ³ã§æžããã¹ããŒãã®æŽæ°ãçºçãããŠããŸããæ¢ã«ãå¯ãããšæããŸããã() => setCount(count - 1)ã®ã»ãã¯ãããã 5 åé£ç¶ã§åŒã³åºãããŠãcount㯠1 ã ãæžããŸãããªããªããsetCount(count - 1)ã§åç
§ãããcountã¯åžžã«ãã®UseStateSample4ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããããšãã®countã ããã§ãã
ããã«å¯Ÿãã()=> setCount(count => count + 1)ã®å Žåã¯ãããã 5 ååŒã³åºãããããšã§count㯠5 å¢ããŸããããã¯ããã®é¢æ°ãåŒã³åºããããã³ã«çŸåšã®countã®å€ãåç
§ãããïŒãããŠããã« 1 ãè¶³ããæ°å€ãæ°ããcountãšãªãïŒããã§ãã
ãã®ããã«ã颿°ãã¯ã³ãã¹ã§è€æ°ååŒã³åºãããããšãæ³å®ãããšã颿°ãçšããã¹ããŒãæŽæ°ïŒäžã®äŸã§èšãã°åŸè ïŒã«ããªããšæ³å®ããåäœã«ãªããªãããšããããŸããç¹°ãè¿ããŸãããçŸåšã®ã¹ããŒãã«äŸåããŠæŽæ°ãè¡ããªããã®ããã«é¢æ°ãã¹ããŒãæŽæ°é¢æ°ã«æž¡ããŸãããã
useEffect
useStateãšäžŠãã§ãã䜿ãã§ãããããã¯ããã®useEffectããã¯ã§ããããã¯ã¬ã³ããªã³ã°åŸã«è¡ãåŠçãæå®ã§ããããã¯ã§ããã¯ã©ã¹ã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ã§ããã°ãcomponentDidMountåã³componentDidUpdateã«ããããçžåœãããã®ã§ãïŒå®éã«ã¯å€å°éãã®ã§ãããããã¯åŸã§èª¬æããŸãïŒã
äŸãã°ã以äžã®äŸã¯ 1 ç§ããšã«è¡šç€ºãããŠããå€ã 1 å¢ããã³ã³ããŒãã³ãã§ããçŸåšè¡šç€ºããŠããå€ãã¹ããŒãã§ç®¡çããããã«ããã£ã玹ä»ããuseStateãšçµã¿åãããŠå®è£
ããŠããŸãã
import * as React from 'react';
const { useState, useEffect } = React;
export const UseEffectSample1 = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const timerId = setTimeout(() => {
setCount(count => count + 1);
}, 1000);
// ã¯ãªãŒã³ã¢ãã颿°ãè¿ã
return () => clearTimeout(timerId);
}, [count]);
return (
<p>
time: <b>{count}</b>
</p>
);
};
ãã®ããã«ãuseEffect㯠2 ã€ã®åŒæ°ãåããŸããè¿ãå€ã¯ãããŸããããŸãã2 ã€ç®ã®åŒæ°ã¯çç¥å¯èœã§ãã1 ã€ç®ã®åŒæ°ã¯ã³ãŒã«ããã¯é¢æ°ã§ããããã®é¢æ°ã¯ã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°å®äºæã«åŒã°ããŸããæåã®ã¬ã³ããªã³ã°ã¯ãã¡ãããåã¬ã³ããªã³ã°ãçºçããããšã«ãåŒã°ããŸãããã ãã第 2 åŒæ°ã§ã³ãŒã«ããã¯é¢æ°ãåŒã¶ã¿ã€ãã³ã°ãå¶åŸ¡ã§ããŸãã第 2 åŒæ°ã¯å€ã®é
åã§ãããé
åã®ããããã®å€ãååãšå€ãã£ããšãã®ã¿ã³ãŒã«ããã¯é¢æ°ãåŒã¶ãšããæå³ã«ãªããŸããçç¥ããå Žåã¯ç¡æ¡ä»¶ãã€ãŸãã¬ã³ããªã³ã°ã®åºŠã«é¢æ°ãåŒã°ããŸã2ã
äžã®ãµã³ãã«ã§ã¯ããŸãæåã®ã¬ã³ããªã³ã°ãå®äºããã¿ã€ãã³ã°ã§useEffectã«æå®ããã³ãŒã«ããã¯é¢æ°ãåŒã³ã ãããŸããããã«ããã1 ç§åŸã«countã¹ããŒããæŽæ°ãããŸããããã«ããã³ã³ããŒãã³ãã®åã¬ã³ããªã³ã°ãçºçããåã³useEffectã®ã³ãŒã«ããã¯é¢æ°ãåŒã°ããŸãããã®ç¹°ãè¿ãã«ããããã®ã³ã³ããŒãã³ã㯠1 ç§ããšã«æ°å€ã 1 ãã€å¢ããŠããã³ã³ããŒãã³ããšãªããŸãã
ä»å第 2 åŒæ°ã¯[count]ã§ããã€ãŸããã¬ã³ããªã³ã°çµäºæã«ãcountã®å€ãååã®ã¬ã³ããªã³ã°ãšå€ãã£ãŠãããuseEffectã®ã³ãŒã«ããã¯ãçºç«ãããšããããšã«ãªããŸããä»åã®å Žåã¯ã¹ããŒããããã ããªã®ã§çç¥ããŠãåãã§ãããä»ã«ãã¹ããŒããããå Žåã«äœèšãªåŠçãçºçããªãããã«ãã广ããããŸãã
ããã§åŒã°ããŠããã³ãŒã«ããã¯é¢æ°ã¯ãããèŠããšé¢æ°ãæ»ãå€ãšããŠããŸããããã¯ã¯ãªãŒã³ã¢ãã颿°ã§ããã¯ãªãŒã³ã¢ãã颿°ã宣èšããå Žåã¯ã次åã®ã³ãŒã«ããã¯ãåŒã°ããåã«ã¯ãªãŒã³ã¢ãã颿°ãåŒã°ããŸãããŸããã³ã³ããŒãã³ããã¢ã³ããŠã³ããããåã«ãã¯ãªãŒã³ã¢ãã颿°ãåŒã°ããŸããèŠããã«ãæç»æã«ã³ãŒã«ããã¯é¢æ°ãåŒã°ããå Žåããã®æç»ãæ¶ããããšãã«å¯Ÿå¿ããã¯ãªãŒã³ã¢ãã颿°ãåŒã°ãããšããããšã§ãããšãŠã䟿å©ã§ããã
äžã®äŸã§ã¯ãæ£ç¢ºã«ã¯ååã¬ã³ããªã³ã° âuseEffectã®ã³ãŒã«ããã¯é¢æ°ãåŒã°ãã â1 ç§åŸã«ã¹ããŒãã倿ŽãããŠåã¬ã³ããªã³ã°ãçºç âã¯ãªãŒã³ã¢ãã颿°ãåŒã°ããâuseEffectã®ã³ãŒã«ããã¯é¢æ°ãåã³åŒã°ããããšããæµãããšã£ãŠããããšã«ãªããŸããããã§ã¯ã¯ãªãŒã³ã¢ãã颿°ã§clearTimeoutãåŒãã§ããŸããããã®ããã«ã³ãŒã«ããã¯é¢æ°ã§çºçããå¯äœçšã®åŸå§æ«ãããã®ãã¯ãªãŒã³ã¢ãã颿°ã®äž»ãªåœ¹ç®ã§ãããã®ã¯ãªãŒã³ã¢ãã颿°ã¯setTimeoutã®çºç«åŸã«åŒã°ããå Žåã¯æå³ããããŸããããã³ã³ããŒãã³ããã¢ã³ããŠã³ããããŠãŸã setTimeoutãçºç«ããŠããªãå Žåã«ããã§ã«ã¢ã³ããŠã³ããããã³ã³ããŒãã³ãã®ã¹ããŒãã倿ŽããŠããŸãã®ãé²ãæå³ããããŸãã
useContext
useContextã¯ãæå®ããã³ã³ããã¹ãã®çŸåšã®å€ãåŸãããã¯ã§ããã³ã³ããã¹ããšããã®ã¯ React 16.3 ã§æèŒãããæ°ããã³ã³ããã¹ã API ã«ãããã®ãæããŠããŸããReact.createContextã§äœæããã³ã³ããã¹ããªããžã§ã¯ããuseContextã«æž¡ãããšã§ããã®ã³ã³ããã¹ãã®çŸåšã®å€ãè¿ãå€ã§åŸãããšãã§ããŸãã
import * as React from 'react';
const { useState, useContext, createContext } = React;
const MyContext = createContext(() => {});
export const UseContextSample = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>
<b>{count}</b>
</p>
<MyContext.Provider value={() => setCount(count => count + 1)}>
<IncrementButton />
</MyContext.Provider>
</div>
);
};
const IncrementButton = () => {
const incrementHandler = useContext(MyContext);
return (
<p>
<button onClick={incrementHandler}>+</button>
</p>
);
};
ãã®äŸã¯çžå€ããããã¿ã³ãæŒããšæ°å€ãå¢ãããšããåçŽãªãµã³ãã«ã§ãããæ°å€ãå¢ãããã¿ã³ãIncrementButtonãšããå¥ã®ã³ã³ããŒãã³ãã«ç§»ããŸããããããªããšããã¿ã³ãæŒãããšãã®åŠçïŒUseContextSampleã®ã¹ããŒãã倿ŽããïŒãIncrementButtonã³ã³ããŒãã³ãã«äŒããå¿
èŠããããŸããäžçªåçŽãªæ¹æ³ã¯ props ã®ã²ãšã€ãšããŠãã®é¢æ°ãæž¡ãããšã§ãããäœæ®µéãäŒæãããªããšãããªããããªå Žåã«ã¯ props ã䜿ãã®ã¯é©ããŠããªãããšããããŸãããã®å Žåã¯ãã®äŸã®ããã«ã³ã³ããã¹ãã䜿ã£ãŠæé»ã«å€ãäŒæãããŸãã
IncrementButtonãåŸæ¥ã® API ã§æžãçŽããšãããªæãã§ããã³ã³ããŒãã³ãã®ãã¹ããç¡ããªã£ãŠç¶ºéºã«æžããã®ãå¬ããã§ããã
const IncrementButton = () => {
return (
<MyContext.Consumer>
{incrementHandler => (
<p>
<button onClick={incrementHandler}>+</button>
</p>
)}
</MyContext.Consumer>
);
};
ãã®ã»ãã®ããã¯
ãããŸã§ã® 3 ã€ããšãŠãè¯ã䜿ããããªããã¯ã§ããããã以å€ã®ããã¯ãç¶ããŠç޹ä»ããŠãããŸããæ¯èŒçãã䜿ããããªããã¯ãã解説ããŠãããŸãã
useReducer
useReducer㯠useState ã®äºçš®ã§ãããã¹ããŒãã宣èšããããã¯ã§ããuseReducerã¯ãã¹ããŒãã®åæç¶æ
ã«å ããŠreducer ãšåŒã°ãã颿°ãæž¡ããŸããçµæãšããŠãçŸåšã®ã¹ããŒãã«å ããŠãã¹ããŒããæŽæ°ãã颿°ã®ä»£ããã« dispatch 颿°ãåŸãããŸãããã® reducer ã dispatch ãšããã®ã¯ Redux çšèªãšããŠããç¥ãããŠããŸãã®ã§ãRedux ãè§Šã£ãããšãããããã¯éŠŽæã¿æ·±ãæŠå¿µã§ãããã
useReducerã«ãã£ãŠäœãããã¹ããŒããæŽæ°ããå Žåã¯ãdispatch颿°ã«ã¢ã¯ã·ã§ã³ãæž¡ããŸããã¢ã¯ã·ã§ã³ãšããã®ã¯ã¹ããŒãã®æŽæ°æç€ºã衚ãå€ã§ãå¥ã«ãªãã§ãæ§ããŸããããã®ã¢ã¯ã·ã§ã³ãåŒæ°ãšããŠãuseReducerã«æž¡ãã reducer ãåŒã³åºãããŸããreducer ãšããã®ã¯é¢æ°ã§ãããã¢ã¯ã·ã§ã³ãšçŸåšã®ã¹ããŒããåãåã£ãŠæ°ããã¹ããŒããè¿ããŸãã
import * as React from 'react';
const { useContext, useReducer, createContext } = React;
const DispatchContext = createContext(() => {});
const reducer = ({ year, month }, action) => {
switch (action) {
case 'increment':
return month === 11
? { year: year + 1, month: 0 }
: { year, month: month + 1 };
case 'decrement':
return month === 0
? { year: year - 1, month: 11 }
: { year, month: month - 1 };
}
};
export const UseReducerSample = () => {
const [state, dispatch] = useReducer(reducer, {
year: 0,
month: 1,
});
return (
<div>
<p>
<b>
{state.year}幎{state.month}ã¶æ
</b>
</p>
<DispatchContext.Provider value={dispatch}>
<ControlButtons />
</DispatchContext.Provider>
</div>
);
};
const ControlButtons = () => {
const dispatch = useContext(DispatchContext);
return (
<p>
<button onClick={() => dispatch('decrement')}>-</button>
<button onClick={() => dispatch('increment')}>+</button>
</p>
);
};
ãã®äŸã¯ãã®ããã«ã¬ã³ããªã³ã°ãããŸãã
ãã®äŸã®ããã«ãuseReducerã«ã¯ 2 ã€ã®åŒæ°ãæž¡ããŸãã1 ã€ç®ã®åŒæ°ã¯ reducer ã§ã2 ã€ç®ã®åŒæ°ã¯åæç¶æ
ã§ããä»åuseReducerã§å®£èšããã¹ããŒãã¯yearãšmonthãšãã 2 ã€ã®ããããã£ãæã£ããªããžã§ã¯ãã§ãã+ãã¿ã³ãš-ãã¿ã³ãæŒããšãæã 1 ã€å¢ããŸãã12 ã¶æã«ãªããšå¹Žã 1 ã€å¢ããŠæã 0 ã«æ»ããŸããïŒãããŸã§ãµã³ãã«ãªã®ã§ã幎ãšã 12 ã§å²ã£ãŠèšç®ããããšããæ¹å€ã¯åãä»ããŸãããïŒ
ãã¿ã³ãæŒããããšãã®ããžãã¯ãreducer颿°ã«ãŸãšãŸã£ãŠããããšãåãããŸãããreducerã®ç¬¬ 1 åŒæ°ãä»ã®ç¶æ
ã§ã第 2 åŒæ°ãã¢ã¯ã·ã§ã³ïŒåçŽãªäŸãªã®ã§ä»åã¯æååïŒã§ãããããŠãuseReducerã«ãã宣èšãããã¹ããŒãã®æŽæ°ã¯ãdispatch颿°ã«ã¢ã¯ã·ã§ã³ãæž¡ãããšã§è¡ããŸããdispatchãåã³ã³ããŒãã³ãã§ããControlButtonsã«æž¡ãã®ã¯å
ã»ã©ç޹ä»ããuseContextã䜿ããŸããã
ä»åã®ãã€ã³ãã¯ã+ãã¿ã³ãæŒããšyearãšmonthãäž¡æ¹åæã«å€åããå¯èœæ§ããããšããããšã§ãããã®ãããªè€éãªå€åãã¢ã¯ã·ã§ã³ãšããæœè±¡çãªåœä»€ã§è¡šãããšã«ãã£ãŠãã¹ããŒããå€åãããåŽïŒdispatchãåŒã³åºãåŽïŒã®åçŽåãšã¹ããŒã倿Žããžãã¯ã®åé¢ãåæã«éæããŠããŸããuseReducerãçšããŠè²ã
ãªç¶æ
ãã²ãšãŸãšãã«å®£èšããå Žåãè²ã
ãªåã³ã³ããŒãã³ããdispatchãçšããŠç¶æ
ãå€åãããã¯ãã§ãããããã®äŸã®ããã«useContextãšçµã¿åãããŠdispatch颿°ãåã³ã³ããŒãã³ããã¡ã«äŒããã®ãç¹ã«é©ããŠããŸããã¹ããŒãã®æŽæ°ã¯ãã¹ãŠdispatchãéããŠè¡ããããdispatch颿°ã²ãšã€äŒããã°ååã§ãããšããã®ãå¬ããç¹ã§ãã
颿°ã«ããã¹ããŒãã®åæå
useReducerã®ç¬¬ 2 åŒæ°ã«åæã¹ããŒããæž¡ã代ããã«ã颿°ãçšããŠã¹ããŒããåæåããããšãã§ããŸãããã®å ŽåãuseReducerã®ç¬¬ 3 åŒæ°ã«åæå颿°ãæž¡ããŸãããŸãã第 2 åŒæ°ã®æå³ãå€ãããŸããæž¡ããåæå颿°ã®åŒæ°ãšããŠuseReducer第 2 åŒæ°ãæž¡ãããŸãããã®æ©èœã¯ãã¹ããŒãã®åæåããžãã¯ãå¥ã®é¢æ°ãšããŠå®çŸ©ãããå Žåãªã©ã«äŸ¿å©ã§ãã
const reducer = ({ year, month }, action) => {
switch (action) {
case 'increment':
return month === 11
? { year: year + 1, month: 0 }
: { year, month: month + 1 };
case 'decrement':
return month === 0
? { year: year - 1, month: 11 }
: { year, month: month - 1 };
}
};
const init = initialMonth => ({
year: 0,
month: initialMonth,
});
export const UseReducerSample2 = ({ initialMonth }) => {
const [state, dispatch] = useReducer(reducer, initialMonth, init);
return (
<div>
<p>
<b>
{state.year}幎{state.month}ã¶æ
</b>
</p>
<DispatchContext.Provider value={dispatch}>
<ControlButtons />
</DispatchContext.Provider>
</div>
);
};
ãã®äŸã§ã¯ãã¹ããŒãã®åæå颿°initãå®çŸ©ããŠuseReducerã®ç¬¬ 3 åŒæ°ã«æž¡ããŸããããã®ã³ã³ããŒãã³ãã<UseReducerSample2 initialMonth={10} />ã®ããã«äœ¿ããšãã0 幎 10 ã¶æãã®è¡šç€ºããã¹ã¿ãŒãããŸãããã®ããã«ã第 2 åŒæ°ãåæã¹ããŒãã§ã¯ãªãã¹ããŒãã®å
ãšãªãå€ã«ããŠã第 3 åŒæ°ã«æž¡ããinit颿°ã§ãããã¹ããŒãã«å€æãããšããæ¹åŒããšã£ãŠããŸãã
ãã®å Žåã¯ç¬¬ 2 åŒæ°ã{year: 0, month: initialMonth}ãšãããšããæããããŸãããåæã¹ããŒããã³ã³ããŒãã³ãã®äžã§å®çŸ©ãããŠããã®ã¯ã©ãã埮åŠã«æããŸããããããæã«ç¬¬ 3 åŒæ°ã䜿ããŸãããã
useReducerã«ã€ããŠããã«è©³ããçè§£ããã
useReducerãããããæ©æµã«ã€ããŠããã«è©³ããæžããèšäºãçšæããŸãããReact Hooksã«å°ãæ
£ããããã«èªãã®ãäžåºŠãããããããŸããã
useMemo
useMemoã¯ããã®åã®éãå€ã®ã¡ã¢åã«äœ¿ããããã¯ã§ãã第 1 åŒæ°ã«å€ãèšç®ãã颿°ãã第 2 åŒæ°ã«èšç®ãããå€ãäŸåããå€ã®äžèŠ§ãæž¡ããŸãã
import * as React from 'react';
const { useMemo } = React;
export const UseMemoSample = ({ n }) => {
const sum = useMemo(() => {
let result = 0;
for (let i = 1; i <= n; i++) {
result += i;
}
return result;
}, [n]);
return (
<div>
<p>
1 + ⊠+ n = <b>{sum}</b>
</p>
</div>
);
};
ããã§å®çŸ©ããUseMemoSampleã¯ã1 ããæå®ããå€ãŸã§ã®åã衚瀺ãããšããæå³äžæãªã³ã³ããŒãã³ãã§ãããããããã®å㯠for ã«ãŒããåããŠèšç®ããŸãã<UseMemoSample n={1000} />ã®ããã«äœ¿ããš1 + ⊠+ 1000 = 500500ãšè¡šç€ºããŸãã
ãã®äŸã¯ãšããããã«ãŒããšãåãåŠçã render ã®äžã«ãã¿æžããããšãã¬ã³ããªã³ã°ãè¡ããããã³ã«ãããèšç®ãããããšã«ãªããŸããèšç®çµæãã¡ã¢åããããããªãã¡ä»¥åèšç®ããçµæãåå©çšã§ãããšãã¯åå©çšãããããšããå Žåã«useMemoã圹ã«ç«ã¡ãŸãã
useMemoã®ç¬¬ 1 åŒæ°ã¯ãå€ãèšç®ãã颿°ãæž¡ããŸããããèªèº«ã«åŒæ°ã¯ãããŸããããprops ã®å€ãªã©ã䜿çšããŠãæ§ããŸããããã®é¢æ°ã®è¿ãå€ãuseMemoã®è¿ãå€ãšãªããŸãããã®é¢æ°ãåŒã³åºãããã®ã¯å€ã®èšç®ãå¿
èŠãšãªã£ããšãã§ããã€ãŸããååã®ã¬ã³ããªã³ã°æããã³åèšç®ãå¿
èŠãšãªã£ããšãã«é¢æ°ãåŒã³åºãããŸããuseMemoã¯ä»¥åã®èšç®ã®çµæãèŠããŠãããåèšç®ãå¿
èŠãªãå Žåã¯æž¡ãã颿°ã¯åŒã³åºãããã以åã®èšç®ã®çµæãè¿ãããŸãã
åèšç®ããã€å¿
èŠãã¯useMemoã®ç¬¬ 2 åŒæ°ã§æå®ããŸããããã¯useEffectã®ç¬¬ 2 åŒæ°ãšåãã§ãããã«æž¡ããå€ã®ãããããå€åãããšãã«åèšç®ãè¡ãªãããŸããä»åã®å Žåã¯èšç®çµæã¯nã«äŸåããŠããããã第 2 åŒæ°ã«[n]ãæž¡ãå¿
èŠããããŸããããã«ãããnãå€åãããšãåèšç®ãè¡ãªãããããã«ãªããŸãã
useCallback
useCallbackã¯useMemoã®äºçš®ã§ããç°¡æœã«èšãã°ãuseCallback(fn, arr)ã¯useMemo(()=> fn, arr)ãšåãã§ããã€ãŸããuseCallbackã¯èšç®ã®å¿
èŠãªãå€ãã¡ã¢åãããšãã«äŸ¿å©ãªããã¯ã§ãã
èšç®ãå¿
èŠãªãã®ã«ã¡ã¢åãšã¯ã©ãããããšããšãæããããããŸããããuseCallbackãšããååã瀺åãããšãããããã¯é¢æ°ãã¡ã¢åããã®ã«äŸ¿å©ã§ãããã€ã³ãã¯ã()=> { ... }ã®ãããªé¢æ°åŒã¯æ¯åæ°ãã颿°ãªããžã§ã¯ããäœããšããç¹ã§ãã
以äžã«useContextã®ãµã³ãã«ãåæ²ããŸãã
export const UseContextSample = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>
<b>{count}</b>
</p>
<MyContext.Provider value={() => setCount(count => count + 1)}>
<IncrementButton />
</MyContext.Provider>
</div>
);
};
ããã§MyContext.Providerã® prop ãšããŠ()=> setCount(count => count+1)ãšãã颿°ãæž¡ããŠããŸããããã¯é¢æ°åŒãªã®ã§ãUseContextSampleãã¬ã³ããªã³ã°ããããã³ã«æ°ãã颿°ãªããžã§ã¯ããäœãããŠãããMyContext.Providerã«æž¡ãããŸããå®ã¯ããã¯è¯ããããŸããããªããªããã³ã³ããã¹ãã«æž¡ãããå€ãå€åãããã³ã«ãã®ã³ã³ããã¹ãã®å€ã䜿çšããã³ã³ããŒãã³ãã¯å
šéšåæç»ããããããäžã®äŸã§MyContextã䜿çšããã³ã³ããŒãã³ããæ¯ååæç»ãããŠããŸãããã§ãã
ããããæã¯useCallbackã®åºçªã§ãã以äžã®ããã«ããããšã§åæç»ãé²ãããšãã§ããŸãã
import * as React from 'react';
const { useState, useContext, useCallback, createContext } = React;
const MyContext = createContext(() => {});
export const UseCallbackSample = () => {
const [count, setCount] = useState(0);
const updateCount = useCallback(() => setCount(count => count + 1), []);
return (
<div>
<p>
<b>{count}</b>
</p>
<MyContext.Provider value={updateCount}>
<IncrementButton />
</MyContext.Provider>
</div>
);
};
const IncrementButton = React.memo(() => {
const incrementHandler = useContext(MyContext);
return (
<p>
<button onClick={incrementHandler}>+</button>
</p>
);
});
ãã®äŸã§ã¯ãMyContext.Providerã«æž¡ã颿°ãuseCallbackãçšããŠã¡ã¢åããŠããŸãã第 2 åŒæ°ã[]ãšããããšã¯ãäžåºŠåæåãããåŸã¯updateCountã¯æ¯ååäžã®é¢æ°ãªããžã§ã¯ããšãªããŸãããã£ãŠãMyContext.Providerã®å€ã¯å€åããŠããªãæ±ããšãªããIncrementButtonã¯åæç»ãããªããªããŸãã
ãã ããIncrementButtonãReact.memoã§å²ãããã«å€æŽãããŠããç¹ã«æ³šæããŠãã ãããããã¯ããã¯ã§ã¯ãªãã®ã§è©³çްã¯çããŸããã芪ã®UseCallbackSampleãåæç»ãããŠãèªåçã«IncrementButtonãåæç»ããªãããã«ãã广ããããŸãããã® 2 ã€ã®æœçã«ããIncrementButtonãåæç»ãããèŠå ãç¡ããªããŸãããã®ããã«useCallbackïŒãuseMemoïŒã¯æé©åã«å©çšããããšãã§ããŸãã
useRef
useRefã¯ãref ãªããžã§ã¯ããäœã£ãŠè¿ãããã¯ã§ãããã® ref ãªããžã§ã¯ãã¯React.createRefã䜿ã£ãŠäœãããšãã§ãããªããžã§ã¯ãã®ããšã§ããuseRefã¯ãåãåŒã³åºãã«å¯ŸããŠã¯åã ref ãªããžã§ã¯ããè¿ããŸããref ãªããžã§ã¯ãã¯currentããããã£ã«ãã®äžèº«ãå
¥ã£ãŠããŸããcurrentã®åæå€ã¯useRefã®åŒæ°ã§æå®ããããšãã§ããŸãã
useRefã®ã²ãšã€ã®çšéã¯ãã³ã³ããŒãã³ãã®ref屿§ã«æž¡ãããã®refãªããžã§ã¯ããäœãããšã§ããuseEffectãšçµã¿åãããäŸãäœã£ãŠã¿ãŸããã
import * as React from 'react';
const { useEffect, useRef } = React;
export const UseRefSample = () => {
const displayAreaRef = useRef();
useEffect(() => {
let rafid = null;
const loop = () => {
// çŸåšæå»ã衚瀺
const now = new Date();
displayAreaRef.current.textContent = `${String(now.getHours()).padStart(
2,
'0',
)}:${String(now.getMinutes()).padStart(2, '0')}:${String(
now.getSeconds(),
).padStart(2, '0')}.${String(now.getMilliseconds()).padStart(3, '0')}`;
rafid = requestAnimationFrame(loop);
};
loop();
return () => cancelAnimationFrame(rafid);
});
return <p ref={displayAreaRef} />;
};
ãã®ã³ã³ããŒãã³ãã¯ãã®ãããªè¡šç€ºãšãªããŸãã
ããã¯ãrequestAnimationFrameãçšããŠãªã¢ã«ã¿ã€ã ã§çŸåšæå»ãããªç§åäœã§è¡šç€ºããã³ã³ããŒãã³ãã§ãããã®ãããªé«é »åºŠãªæŽæ°ãã¹ããŒããçšããŠè¡ãã®ã¯è² è·ãé«ãããªæ°ãããã®ã§useEffectãçšããŠçŽæ¥ DOM æäœãè¡ã£ãŠããŸãã
çŽæ¥ DOM æäœãè¡ãã«ã¯ãã¬ã³ããªã³ã°åŸã«çã® DOM ããŒããååŸããæ¹æ³ããããŸãããã®æ¹æ³ãã³ã³ããŒãã³ãã®ref屿§ïŒ<p ref={displayAreaRef} />ïŒã§ãããã®ref屿§ã«æž¡ãããã® ref ãªããžã§ã¯ããuseRef()ããã¯ã§äœã£ãŠããŸããref屿§ã®å¹æã«ãããã¬ã³ããªã³ã°æã« ref ãªããžã§ã¯ãã®currentããããã£ã« DOM ããŒããã»ãããããŸãããã®äŸã§ã¯useEffectã®ãã³ãã©ã®äžãããã®æ
å ±ã䜿çšããŠããŸãã
ã¬ã³ããªã³ã°é倿°ãšã㊠useRef ã䜿çšãã
åŸæ¥ãref ãªããžã§ã¯ããšããã®ã¯å°ããäžèšã®äŸã®ããã« DOM ãªããžã§ã¯ããžã®åç
§ãåŸãã®ã«äœ¿ãããŠããŸãããããããããã¯ã®äžçã«ãããŠã¯useRefã ref ãªããžã§ã¯ãã¯ãã®äŸ¿å©ããããã«å¢ããŠããŸãã
ãã€ã³ãã¯ãuseRefãè¿ããªããžã§ã¯ãã¯ã¬ã³ããªã³ã°éã§æ¯ååãã§ãããšããããšã§ããç¹ã«useEffectã䜿çšããå Žåã«ãã¬ã³ããªã³ã°éã§æ
å ±ãå
±æããå Žåã«äœ¿çšå¯èœã§ãã
äŸãã°ãcomponentDidUpdateã¯ãååã® propsããšãååã® stateããåç
§å¯èœã§ãããuseEffectã«ã¯ãã®æ©èœã¯ãããŸããã§ãããååã® props ãªã©ãå©çšãããå Žåã¯ããã®æ
å ±ãèªåã§useRefã«ä¿åããŠããããšã«ãªããŸãã
以äžã®äŸã¯ãèªåãåã¬ã³ããªã³ã°ãããåæ°ãèŠããŠããã³ã³ããŒãã³ãã§ããïŒæ¬åœã¯ããããçšéã§useEffectã䜿ããã«ããžãã¯ã§äœãšãããã»ããããã§ããããšãããåã¬ã³ããªã³ã°ãããåæ°ãå¿
èŠãªã®ã£ãŠã©ããªå Žé¢ãªã®ã§ãããããïŒ
export const UseRefSample2 = () => {
const displayAreaRef = useRef();
const renderCountRef = useRef(0);
useEffect(() => {
renderCountRef.current++;
displayAreaRef.current.textContent = String(renderCountRef.current);
});
return (
<p>
ãã®ã³ã³ããŒãã³ãã¯
<b ref={displayAreaRef} />
åæç»ãããŸããã
</p>
);
};
ãããšåããã®ãã¯ã©ã¹ã³ã³ããŒãã³ãã§æžããšãããªæãã§ããuseRefã§åŸã ref ãªããžã§ã¯ããããããã³ã³ããŒãã³ãã®ïŒã¹ããŒãã§ã¯ãªãïŒããããã£ã«å¯Ÿå¿ããŠããããšãåãããšæããŸããããã«ããŠãããã£ã±ãããã¯ãçšãã颿°ã³ã³ããŒãã³ãã®ã»ããã·ã³ãã«ã§ããã§ããïŒå Žåã«ããããŸããïŒã
export class UseRefSample2 extends React.Component {
constructor(props) {
super(props);
this.displayArea = React.createRef();
this.renderCount = 0;
}
render() {
return (
<p>
ãã®ã³ã³ããŒãã³ãã¯
<b ref={this.displayArea} />
åæç»ãããŸããã
</p>
);
}
_effect() {
this.renderCount++;
this.displayArea.current.textContent = String(this.renderCount);
}
componentDidMount() {
this._effect();
}
componentDidUpdate() {
this._effect();
}
}
useLayoutEffect
useLayoutEffect㯠useEffectã®äºçš®ã§ããåºæ¬çãªäœ¿ãæ¹ã¯useEffectãšåãã§ãããã³ãŒã«ããã¯é¢æ°ãåŒã°ããã¿ã€ãã³ã°ãéããŸããå
·äœçã«ã¯ãuseEffectã¯ã¬ã³ããªã³ã°ã®çµæãæç»ãããåŸã«åŒã³åºãããŸãããuseLayoutEffectã¯ã¬ã³ããªã³ã°çµæãDOMã«åæ ãããåŸæç»ãããåã«åŒã³åºãããŸãã
ã¬ã³ããªã³ã°çµæãæç»ãããåã«ã³ãŒã«ããã¯ã®åŠçãèµ°ããšããç¹åŸŽã®ãããuseLayoutEffectã®åŠçã¯ã¬ã³ããªã³ã°ããããã¯ããã¬ã³ããªã³ã°çµæããŠãŒã¶ãŒã«èŠããã®ãé
å»¶ãããŸããã§ãããããã®å¿
èŠããªãå Žåã¯useEffectã䜿ãã¹ãã§ãããšãããŠããŸããã¡ãªã¿ã«ãã¯ã©ã¹ã³ã³ããŒãã³ãã®componentDidMountãcomponentDidUpdateã®ã¿ã€ãã³ã°ã¯ãã®useLayoutEffectãšåãã§ããuseEffectã¯ãã¬ã³ããªã³ã°ããããã¯ããªããªã£ããšããç¹ã§ãããã®é²å圢ã§ãããšèšããã§ãããã
useLayoutEffectã䜿ãäŸãæããŠã¿ãŸããã€ãå
ã»ã©ã®useRefã®äŸãæãåºããŠãã ããã
export const UseRefSample2 = () => {
const displayAreaRef = useRef();
const renderCountRef = useRef(0);
useEffect(() => {
renderCountRef.current++;
displayAreaRef.current.textContent = String(renderCountRef.current);
});
return (
<p>
ãã®ã³ã³ããŒãã³ãã¯
<b ref={displayAreaRef} />
åæç»ãããŸããã
</p>
);
};
ããã®è¿ãå€ãèŠãŠã¿ããšãbèŠçŽ ã®äžèº«ã¯æå空ã§ããuseEffectã®ã³ãŒã«ããã¯ã«ãã£ãŠãã®äžèº«ãåããããŸãããããã«åé¡ããããŸããuseEffectã®ã³ãŒã«ããã¯ã¯ã¬ã³ããªã³ã°ãæç»åŸã«åŒã³åºããããšããããšã¯ããã®äžèº«ã空ã®ç¶æ
ãäžç¬ãŠãŒã¶ãŒã«èŠããŠããŸãã®ã§ããå®éãäžã®ç»åã®ãããªæç»ã衚瀺ãããŠããŸããŸãã
useLayoutEffectã䜿çšããããã«æžãæããããšã§ãã®çŸè±¡ãåé¿ã§ããŸãã
import * as React from 'react';
const { useLayoutEffect, useRef } = React;
export const UseLayoutEffectSample = () => {
const displayAreaRef = useRef();
const renderCountRef = useRef(0);
useLayoutEffect(() => {
renderCountRef.current++;
displayAreaRef.current.textContent = String(renderCountRef.current);
});
return (
<p>
ãã®ã³ã³ããŒãã³ãã¯
<b ref={displayAreaRef} />
åæç»ãããŸããã
</p>
);
};
useDebugValue
ãããæããäžçªæ°ããããã¯ã§ãReact Hooksãæã¯è¿œã£ãŠãããšããæ¹ã¯ç¥ããªããããããŸããããã®åã®éããããã¯ãããã°ã«äœ¿ããããã¯ã§ããå ·äœçã«ã¯ãã«ã¹ã¿ã ããã¯ã®ãããã°æ å ±ãReactã®éçºè ããŒã«çšæ¡åŒµæ©èœã«è¡šç€ºãããããšãã§ããŸãã
ããã¯å ã»ã©ã®ãã¬ã³ããªã³ã°åæ°ãèŠããŠããã³ã³ããŒãã³ãããããŒã¹ã«ããäŸã§ãã
import * as React from 'react';
const { useEffect, useRef, useDebugValue } = React;
const useRenderCount = () => {
const renderCountRef = useRef(0);
useDebugValue(
`ãã®ã³ã³ããŒãã³ãã¯${renderCountRef.current}ååæç»ãããŸãã`,
);
useEffect(() => {
renderCountRef.current++;
});
};
export const UseDebugValueSample = () => {
useRenderCount();
return <p>ãã®ã³ã³ããŒãã³ããéçºè
ããŒã«ã§èŠããšåæç»æ°ã衚瀺ãããŸã</p>;
};
ããã§å®çŸ©ãããŠããuseRenderCount颿°ã¯ã«ã¹ã¿ã ããã¯ã§ããã«ã¹ã¿ã ããã¯ã«ã€ããŠã¯çè
ã®ä»¥åã®èšäºã«è²ããŸãããèŠããã«ååãuseã§å§ãŸããã ã®é¢æ°ã§ããæ®éã¯äžã®äŸã®ããã«ãããã€ãã®ããã¯åŒã³åºãããŸãšããŠé¢æ°ã«ãããã®ãã«ã¹ã¿ã ããã¯ã§ãããã ã®é¢æ°ãšããããšã¯ãããã³ã³ããŒãã³ãããuseRenderCountã«ã¹ã¿ã ããã¯ãåŒã³åºãã®ã¯ããã®äžèº«ã«æžãããŠããããã¯ãå
šéšåŒã³åºãã®ãšåãã§ããäœãç¹æ®ãªããšã¯ãããŸããã
ãã ãuseDebugValueããã¯ã¯èªåãã©ã®ã«ã¹ã¿ã ããã¯ããåŒã³åºãããã®ãæ€ç¥ããŸã3ããããŠã察å¿ããã«ã¹ã¿ã ããã¯ã®æšªã«æå®ãããããã°æ
å ±ã衚瀺ããŸãã
å®éããã®UseDebugValueSampleãReactçšæ¡åŒµæ©èœã§èŠããšäžã®ç»åã®ããã«è¡šç€ºãããŠããŸããuseDebugValueããã¯ã§æå®ããå€ãuseRenderCountã«ã¹ã¿ã ããã¯ã®ãããã°æ
å ±ãšããŠè¡šç€ºãããŠããããšãåãããŸãã
ãã®ããã¯ã¯ãããããå¢ããã§ããããã«ã¹ã¿ã ããã¯ãã©ã€ãã©ãªã§æäŸãããããªå Žåã«äŸ¿å©ãããããŸããã
ãããã°æ å ±ã®é å»¶èšç®
useDebugValueã®åŒã³åºãã¯ãã ã®JavaScriptã³ãŒãã§ããããããã¯ã®åŠçæã«ã¯æ®éã«å®è¡ãããŸããã€ãŸããéçºè
ããŒã«ã䜿çšããŠããªãäžè¬ãŠãŒã¶ãŒãã¢ããªãå®è¡ããŠããå Žåã§ãã£ãŠãuseDebugValueã®åŒã³åºãã¯ïŒå®éèŠãããããšã¯ãªãã®ã§ç¡æå³ã§ããïŒè¡ãããŠããŸãã
åã£ããããã°æ
å ±ã衚瀺ãããå ŽåãuseDebugValueã®åŒæ°ã®èšç®ãå€å°éãåŠçã«ãªããããããŸããããã®ãããªå Žåãéçºè
ããŒã«ã䜿ããªããŠãŒã¶ãŒã®åŠçãéããªã£ãŠããŸãã®ã¯æãŸãããããŸããããã®ãããªäºæ
ãé¿ããããã«ãuseDebugValueã®ç¬¬2åŒæ°ã«ãçã®ããŒã¿ããããã°æ
å ±ã«å å·¥ãã颿°ãæž¡ãããšãã§ããŸãããããããšããã®é¢æ°ã¯å®éã«ãããã°æ
å ±ã衚瀺ããéã«å®è¡ãããŸããããã«ããããããã°æ
å ±ãå¿
èŠãªãå Žåã«äœèšãªèšç®ãçãããšãã§ãããšããããã§ãããã®æ©èœã¯ä»¥äžã®ããã«äœ¿ããŸãã
useDebugValue(
renderCountRef.current,
count => `ãã®ã³ã³ããŒãã³ãã¯${count}ååæç»ãããŸãã`,
);
ãã®äŸã§ã¯ã第1åŒæ°ã¯ã«ãŠã³ãæ°ãšããçã®ããŒã¿ã«ãªãããããæååãžãšå å·¥ããåŠçã¯é å»¶ãããããã«ãªããŸããã
useImperativeHandle
ãããæåŸã®ããã¯ã§ãããã®ããã¯ã¯ãã³ã³ããŒãã³ãã®ã€ã³ã¹ã¿ã³ã¹ãæã€ã¡ãœãããçæããããšãã§ããããã¯ã§ããäœ¿ãæ¹ã¯äŸãåç
§ããŠãã ããããªããã³ã³ããŒãã³ãã®ã€ã³ã¹ã¿ã³ã¹ãšããã®ã¯ãrefã§ååŸã§ãããªããžã§ã¯ãã®ããšã§ãã<div ref={myRef} />ã®ããã«DOMèŠçŽ ã«å¯ŸããŠrefã䜿ã£ãå Žåã¯çã®DOMããŒããåŸãããŸããã<MyComponent ref={myRef} />ã®å Žåã¯MyComponentã³ã³ããŒãã³ãã®ã€ã³ã¹ã¿ã³ã¹ïŒã®ãããªãã®ïŒãåŸãããããšã«ãªããŸããMyComponentåŽãuseImperativeHandleããã¯ã䜿ãããšã§ãããã§åŸãããã€ã³ã¹ã¿ã³ã¹ã«ã¡ãœãããçããããšãã§ããŸãã
次ã®äŸã¯ãå°ãåã«åºãŠãããçŸåšæå»ããªã¢ã«ã¿ã€ã ã«è¡šç€ºãããµã³ãã«ãæ¹é ãããã®ã§ãã
import * as React from 'react';
const {
useEffect,
useRef,
useCallback,
useImperativeHandle,
forwardRef,
} = React;
export const UseImperativeHandleSample = () => {
const clockRef = useRef();
// ã¹ã¿ãŒããã¿ã³ãæŒãããšãã®åŠç
const onStart = useCallback(() => {
clockRef.current.start();
}, []);
// ã¹ããããã¿ã³ãæŒãããšãã®åŠç
const onStop = useCallback(() => {
clockRef.current.stop();
}, []);
return (
<div>
<Clock ref={clockRef} />
<p>
<button onClick={onStart}>åé</button>
<button onClick={onStop}>忢</button>
</p>
</div>
);
};
const Clock = forwardRef((_props, ref) => {
// æå»ã衚瀺ããå Žæã®ref
const displayAreaRef = useRef();
// ãªã¢ã«ã¿ã€ã 衚瀺ããªã³ãã©ããã®ref
const enabledFlagRef = useRef(true);
// ãªã¢ã«ã¿ã€ã ã«æå»ã衚瀺ããåŠç
useEffect(() => {
let rafid = null;
const loop = () => {
// ãªã¢ã«ã¿ã€ã 衚瀺ããªã³ã®ãšãã®ã¿è¡šç€ºãæŽæ°
if (enabledFlagRef.current) {
// çŸåšæå»ã衚瀺
const now = new Date();
displayAreaRef.current.textContent = `${String(now.getHours()).padStart(
2,
'0',
)}:${String(now.getMinutes()).padStart(2, '0')}:${String(
now.getSeconds(),
).padStart(2, '0')}.${String(now.getMilliseconds()).padStart(3, '0')}`;
}
rafid = requestAnimationFrame(loop);
};
loop();
return () => cancelAnimationFrame(rafid);
});
// ã³ã³ããŒãã³ãã®ã€ã³ã¹ã¿ã³ã¹ãæã€ã¡ãœããã宣èš
useImperativeHandle(ref, () => ({
start() {
enabledFlagRef.current = true;
},
stop() {
enabledFlagRef.current = false;
},
}));
return <p ref={displayAreaRef} />;
});
æåŸãªã®ã§äŸãå°ãé·ããªã£ãŠããŸããäžã§å®çŸ©ãããŠããClockã³ã³ããŒãã³ããuseImperativeHandleããã¯ã䜿çšããŠstartãšstopãšãã2ã€ã®ã¡ãœããã宣èšããŠããŸãããã®ã³ã³ããŒãã³ãã¯enabledFlagRefã®å€ãçšããŠè¡šç€ºãæŽæ°ãããã©ãããå¶åŸ¡ããŠããããã®2ã€ã®ã¡ãœãããçšããŠãããå€éšããå¶åŸ¡ã§ããããã«ããããšããéèã§ãã䜿ãåŽã§ããUseImperativeHandleSampleã³ã³ããŒãã³ãã¯ãclockRefã«Clockã³ã³ããŒãã³ãã®ã€ã³ã¹ã¿ã³ã¹ãå
¥ããŠããã¿ã³ãæŒããããšãã®startãstopãåŒã³åºãããã«ãªã£ãŠããŸãã
useImperativeHandleã䜿ããšãã®æåã®ãã€ã³ãã¯ãããèŠããšClockãforwardRefãšãã颿°ã«å
ãŸããŠããç¹ã§ããforwardRefã¯å€§éæã«èšãã°é¢æ°åã³ã³ããŒãã³ãã®refãå å·¥ããããšãã«äœ¿ããã®ã§ããä»åã¯ãŸãã«useImperativeHandleã«ãã£ãŠrefã«ã¡ãœãããçããããšããŠããã®ã§ããã
forwardRefã®åŒæ°ãšããŠé¢æ°ã³ã³ããŒãã³ããæž¡ãã®ã§ããã第2åŒæ°ãšããŠrefãæž¡ãããããã«ãªã£ãŠããŸããããããã®ãŸãŸuseImperativeHandleã®ç¬¬1åŒæ°ãšãªããŸãã第2åŒæ°ã¯ãªããžã§ã¯ããè¿ã颿°ã§ããè¿ããããªããžã§ã¯ããæã£ãŠããã¡ãœãããããã®ãŸãŸãã®ã³ã³ããŒãã³ãã®refã®ã¡ãœãããšãªããŸãã
ååã«ã€ããŠ
Imperativeãšããã®ã¯ãæç¶ãçããšããããšã§ããæç¶ãçãšããã®ã¯ãpropsçã«ãã£ãŠå®£èšçã«UIãå®çŸ©ããReactã®æµåããå€ããŠããããšãæå³ããŠããŸããå®éããã®äŸã ã£ãŠuseImperativeHandleã䜿ãå¿
ç¶æ§ãããããã§ã¯ãªãããªã³/ãªãã®ãã©ã°ãpropsã§æž¡ãããšãå¯èœã§ããããããã³ã³ããŒãã³ãã«ã¡ãœãããçãããšããã®ã¯ã³ã³ããŒãã³ããpropsïŒãã³ã³ããã¹ãïŒä»¥å€ã®ææ®µã§å¶åŸ¡ããããšããããšã§ããããçã£åããReactã®ããæ¹ã«åããŠããã®ããåããã«ãªããšæããŸããããã§ãéèŠããããããããã®ããã¯ã远å ãããã®ã§ãããããããŸãç©æ¥µçã«äœ¿ããã®ã§ããªãããšããã¡ãã»ãŒãžãååã«è¡šããŠããŸãã
ãŸãšã
以äžã§ãReact Hooksã®æåã®æ£åŒçãå°å
¥ãããReact 16.8ã«ååšããããã¯ãå
šãŠè§£èª¬ããŸãããå人çã«ãã䜿ããããªã®ã¯useStateãšuseEffectãããšuseRefãããã§ããuseRefã¯useEffectã®ããžãã¯ãè€éåããŠãããåºçªãå¢ããŠããŸããå¯äœçšãè€éåãããã®ã¯ããŸãè€ããããããšã§ã¯ãããŸãããã
éäžäœåãã¯ã©ã¹ã³ã³ããŒãã³ããšã®æ¯èŒãæã¿ãŸãããããããåŸçºã®APIã ããã£ãŠãããã·ã³ãã«ã§çŽæçãªèšè¿°ãå¯èœã«ãªã£ãŠããã®ããåããã«ãªã£ãããšã§ãããããããã颿°ã³ã³ããŒãã³ãèªäœãã·ã³ãã«ãªAPIãšããããšãããããœãŒã¹ã³ãŒãã®ã·ã³ãã«ãã«å€§ããè²¢ç®ããŠãããŸãããŸããæå颿°ã³ã³ããŒãã³ãã§æžããŠããã®ã«ç¶æ ãå¿ èŠã«ãªã£ãŠããŸã£ããšãã«ãã¯ã©ã¹ã³ã³ããŒãã³ãã«æžãçŽãå¿ èŠããªããšããã®ãå¬ããç¹ã§ã4ã
éäžäœåããªã³ã¯ããŸããããçè ã®ä»ã®èšäºã«ã«ã¹ã¿ã ããã¯ãåãæ±ã£ããã®ããããŸããä»å玹ä»ããããã¯ãã¡ãçµã¿åãããŠã«ã¹ã¿ã ããã¯ãäœãããšããReact Hooksã®æ¬è³ªã§ãããšèšã£ãŠãéèšã§ã¯ãããŸãããããããããèªã¿çµãã£ãŠãªãã»ã©ãšæã£ãããªãã¯ãŸã React Hooksã®ã¹ã¿ãŒãã©ã€ã³ã®3ã¡ãŒãã«ãããæåã«ããç¶æ ãªã®ã§ãããã²ãã¡ãã®èšäºãèªãã§React Hooksã®ã¹ã¿ãŒããåã£ãŠãã ããã
-
äžå¿è£è¶³ããŠãããšãã¯ã©ã¹ã³ã³ããŒãã³ããªã©ã®æ§æ¥ã®æ©èœã React Hooks ã«åã£ãŠä»£ããããŠå»æ¢ããããšããäºå®ã¯ä»ã®ãšãããããŸãããã§ããããReact Hooks ãé¿ããªãã React ã䜿ãç¶ããããšãå¯èœã§ããçè ã¯ãããã人ïŒ/ããŒã ïŒã¯ React ã䜿ãã®ã«åããŠããªããšããèª¬ãæšããŸããã â©
-
第 2 åŒæ°ã®çç¥ãšã第 2 åŒæ°ã«
[]ãæå®ããã®ãšã¯ç°ãªããšããç¹ã«æ³šæããŠãã ããã第 2 åŒæ°ãçç¥ããå Žåã¯ã¬ã³ããªã³ã°ããšã«ã³ãŒã«ããã¯é¢æ°ãåŒã°ããŸããã[]ãæå®ããå Žåã¯ååã®ã¬ã³ããªã³ã°ã§ã®ã¿ã³ãŒã«ããã¯é¢æ°ãåŒã°ããŸãã â© -
ã¡ãããšèª¿ã¹ãããã§ã¯ãããŸããããã©ããã
Errorãªããžã§ã¯ããçæããŠã³ãŒã«ã¹ã¿ãã¯ãå ¥æããŠããããã§ãã â© -
recomposeã䜿ã£ãŠãã人ã¯é¢æ°ã³ã³ããŒãã³ãã®ãŸãŸã§ããããããšæã£ããããããŸãããããã¯ããæå³ã§æ£ãããReact Hooksã¯recomposeã®é²åç³»ãšèããããšãã§ããŸãããªããrecomposeã¯React Hooksã®ç»å Žãšåæã«æ©èœè¿œå çã®åæ¢ã宣èšãããŸãããä»åŸã¯React Hooksãrecomposeã«åã£ãŠä»£ããããšã«ãªããŸãã â©



