サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

React + Redux入門 07: React ReduxのフックuseDispatch()とuseSelector()を使う


React Redux 7.1.0からフック(Hook)が備わりました。React標準のフックが状態などの機能を関数コンポーネントにつなぐ(hook into)のに対して、ReduxのStoreにつなぐのがReact Reduxのフックです。高階(Higher-Order)コンポーネントのconnect()を使わずに済み、コードの組み立てがすっきりします。

01 useDispatch()でStoreからdispatch()を参照する

connect()でラップしたコンポーネントを、フックで書き替えてみるのがわかりやすいでしょう。「React + Redux入門 02: フィールドに入力したテキストを項目リストに加える」のつぎの作例(サンプル001)で試すことにします。

サンプル001■react-redux-todos-02

まず、モジュールsrc/components/AddTodo.jsです。connect()が引数なしに呼び出されて、ラップされた関数コンポーネント(AddTodo)は、受け取ったpropsからdispatch()を取り出して使っています。ReduxのStroreからdispatchを参照するのがuseDispatch()です。このフックを用いることにより、つぎのようにconnect()によるラップが外せます。

src/components/AddTodo.js

// import { connect } from 'react-redux';
import { useDispatch } from 'react-redux';


// const AddTodo = ({ dispatch }) => {
const AddTodo = () => {
	const dispatch = useDispatch();

	return (
		<div>
			<form onSubmit={(event) => {

				// dispatch(addTodo(text));
				dispatch(addTodo(text));
			}}>

			</form>
		</div>
	);
};

// export default connect()(AddTodo);
export default AddTodo;

02 useSelector()でStoreのstateを参照して処理する

もうひとつ手を加えるのは、モジュールsrc/components/TodoList.jsです。connect()に渡す第1引数(mapStateToProps)で、stateからデータ(todos)を取り出して関数コンポーネントの引数(props)に与えていました。Storeのstateを参照するフックはuseSelector()です。引数に渡した関数はstateを受け取るので、取り出したい値を返してください。connect()とともに、その第1引数として定めた関数も要らなくなりました。

src/components/TodoList.js

// import { connect } from 'react-redux';
import { useSelector } from 'react-redux';

// const TodoList = ({ todos }) => (
const TodoList = () => {
	const todos = useSelector((state) => state.todos);

};

/* const mapStateToProps = (state) => ({
	todos: state.todos
}); */

/* export default connect(
	mapStateToProps
)(TodoList); */
export default TodoList;

03 React Reduxのフックで書き直した作例

以上ふたつのモジュールをReact Reduxのフックに書き替えたことにより、前掲サンプル001からconnect()の呼び出しがなくなりました。ふたつのモジュールの記述全体をまとめたのが、以下のコード001と002です。併せて、動きを確かめるための書き直した作例を、CodeSandboxに公開しました(サンプル002)。今回はごく簡単なコードサンプルで、試したふたつのフックの構文ももっともシンプルなものです。次回は、Redux公式サイトの「Example: Todo List」をふたつのフックで書き直します。

コード001■src/components/AddTodo.js


import React from "react";
import { useDispatch } from "react-redux";
import { addTodo } from "../actions";

const AddTodo = () => {
	const dispatch = useDispatch();
	let input;
	return (
		<div>
			<form
				onSubmit={event => {
					event.preventDefault();
					const text = input.value.trim();
					input.value = "";
					if (!text) {
						return;
					}
					dispatch(addTodo(text));
				}}
			>
				<input ref={element => (input = element)} />
				<button type="submit">Add Todo</button>
			</form>
		</div>
	);
};

export default AddTodo;

コード002■src/components/TodoList.js


import React from "react";
import { useSelector } from "react-redux";
import Todo from "./Todo";

const TodoList = () => {
	const todos = useSelector(state => state.todos);
	return (
		<ul className="todo-list">
			{todos.map(todo => (
				<Todo key={todo.id} {...todo} />
			))}
		</ul>
	);
};

export default TodoList;

サンプル002■react-redux-todos-07

React + Redux入門


作成者: 野中文雄
作成日: 2020年04月29日


Copyright © 2001-2020 Fumio Nonaka.  All rights reserved.