見出し画像

【React】基本のHooks / useState(), effectState, useContext

Hooksとは?

React の機能を “接続する (hook into)” ための関数。
フックは React をクラスなしに使うための機能。関数コンポーネントで使用。

useState()

React本体に関数コンポーネント専用の保存領域を作成してもらい、データを読み書きできるフック。

const { Component } = React;

function CountButton(props: any){
 const clicked = () =>{
   // 親コンポーネントのstateを更新
   props.onClick((countText: number) => countText + 1);
 }
 return(<button onClick={()=> clicked()}>count</button>);
}

function CountText(props: any){
 return(<p>カウント:{props.countText}</p>);
}

function App(){
 const [countText, setCount] = React.useState(100);
   // onClick={setCount}で子コンポーネントの値を取得
   return (
     <div className="parentContainer">
       <div className="childContainer">
         <CountButton onClick={setCount}/>
       </div>
       <div className="childContainer">
         <CountText countText={countText}/>
       </div>
     </div>
   );
}

ReactDOM.render(<App />, document.querySelector(".container"));


useEffect()

コンポーネントのレンダリング後に実行されるフック。
「DOMの操作」「ウェブAPIとの通信」などはuseEffect内で行う。

DOM操作は、DOM上に要素が存在しないと取得時nullになるためuseEffect内での操作が必要。

APIの通信はレンダリングとは関係ない処理になるため、useEffectで遅延実行します。
基本的に関数コンポーネントの中にはレンダリングに関する処理しか書きません。

const { Component } = React;

function App(){
	const [countText, setCount] = React.useState(0);
	
	// レンダリングと関係ない処理はuseEffect内に記入。
	// ここでは1秒ずつ+1していく処理はレンダリングと関係ない。
	React.useEffect(() => {
		// setIntervalで1000msごとにcountTextに+1
		const timer = setInterval(()=>{
			setCount(countText + 1)
		},1000);
		
		// 新しいtimerが発行されるため、古いtimerはclearIntervalで破棄していく
		// 破棄しないとtimerが溜まっていくため処理が重くなっていく
		return () => {
		  clearInterval(timer)
		}
	// 第二引数の変数に変更があった場合のみ指定された処理が実行される。
	// 第二引数は省略可能
	}, [countText]);
	
	return (
    <div>
	   <h1>カウント:{countText}s</h1>
    </div>
  )
}

ReactDOM.render(<App />, document.querySelector(".container"));



useContext()

Reduxを使うほど規模の大きいプロジェクトではないが、データを共有しやすくなるフック。

// Reduxを使わずに親子コンポーネント間以外の値のやり取りをしやすくする
// Contextとは?:同じコード記述やプログラム上の要素が、その置かれているプログラム内での位置や、実行される際の内部状態などによって異なる振る舞いをしたり、異なる制約を受けたりすることを指してコンテキストということがある。

const { Component } = React;

// 1.まずはここでコンテキストを作成。
const TextContext = React.createContext("");

// 親要素
function App() {
	const [changeText, setText] = React.useState('');
	
	const inputText = (event) => {
		console.log(event.target.value);
		setText(event.target.value);
	}
	
	return (
// 2. 1 で生成した `Context` オブジェクトの `Provider` をコンポーネントツリーの上方に差し込む
// 3.valueで値を渡す
		<TextContext.Provider value={changeText}>
			<p>useContextを使って子要素を通さずにデータを共有する</p>
			<div className="parent-wrap">
				<p>親要素 : 
					<input type="text" value={changeText} onChange={inputText}>
					</input>
				</p>
				<Child/>
			</div>
		</TextContext.Provider>
	);
}

// 子要素
function Child(){
	return(
		<div className="child-wrap">
			<p>子要素</p>
			<Grandchild/>
		</div>
	);
}

// 孫要素
function Grandchild(){
// 4.差し込んだ `Provider` の子孫にあたるコンポーネントで `useContext()` を使って値を取得する
	const text = React.useContext(TextContext);
	
// 5.出力
	return(
		<div className="grand-child-wrap">
			<p>孫要素:{text}</p>
		</div>
	);
}

ReactDOM.render(<App />, document.querySelector(".container"));


Hooksの注意点

コンポーネントの中で呼び出されるHooksは必ず同じ順番で同じ回数呼び出されるようにする。

ifやforの中にHooksを入れて、場合によってHooksの順番や実行回数が変わることは禁止。




この記事が気に入ったらサポートをしてみませんか?