æ¥ãã 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
ã«åã£ãŠä»£ããããšã«ãªããŸãã â©