どうもエンジニアののりにぃです。
最近Reactを学習しているのですが、「useState」などhookは必ずといっていいほど利用されています。
つまり、Reactを学ぶ上でhookを理解せずにコードを読むことはできないということです。
なので今回は、実際に作成したTodoアプリを参考にReact hookの解説をしていきます!
また今回はこちらの動画を参考にReactとRailsを使ってTodoアプリを作成しました。
Todoアプリの中で使用した技術も合わせて解説しますので、useState()やaxiosが理解できていない方は読んでみて下さい!
なお、この動画ではReact Router V5を利用し作成されております。僕の作成したTodoアプリではV6の書き方に対応しているので、よかったら参考にしてみてください!
GithubのURLも載せておきます。
https://github.com/norihiro9779/rails_api_todo_app
React hooksに関して学べば、グッとコードが読みやすくなるよ!!
【ジャンルが豊富で学びたい講座がきっとみつかる】
習得したいスキルが明確で年収アップのために学習している方!
- ジャンルが豊富で学びたい講座がきっとみつかる
- お手頃な価格帯
- 学びやすい多彩な機能
オンライン完結で手軽に学べるプラットフォームです!
React hookとは?
そもそもhooks(フック)とはなんでしょうか?
公式サイトでは、hook について以下のように説明してあります。
フック (hook) は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。
React 公式サイト
つまり、hook は Reactの state やライフサイクルの機能などを、関数コンポーネント内に使用できるようにするための関数といえます。
userState()とは?
import React, { useState } from 'react'
# todo state変数名
# setTodo state変更関数名
# initialTodoState state初期値
const [todo, setTodo] = useState(initialTodoState)
const initialTodoState = {
id: null,
name: "",
is_completed: false
}
useState()は、関数コンポーネントでstateを管理するためのReactフックです。
大前提としてuseState関数を1行目のようにインポートして利用することができます。
書き方が見慣れないかもしれないので、それぞれコメントを参考にしてみてください。
constで宣言した後、配列で[todo, setTodo]と記載しています。
今までであれば、this.state = {todo: ''}やthis.setState = {setTodo: '~'}のように利用していた記載が、一行で使用できるようになっています。
そして右辺に関してはuseState関数を利用してカッコの中に初期値を入れています。
まとめると以下の通りです。
- 1つ目の要素:
stateの現在の値 - 2つ目の要素:
stateの現在の値を更新するための関数 stateが更新されてもinitialTodoStateはinitialTodoStateとして保持される
コードを読み解いてみよう
では、Githubに公開しているコードの一部から実際どのように利用されているのか読み解いていきましょう。(app/javascript/components/AddTodo.jsから抜粋してます。react-toastifyを利用した通知機能は今回は解説しません。)
挙動としては以下のように動きます。

import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import axios from 'axios'
import styled from 'styled-components'
import { toast } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
import { FiSend } from 'react-icons/fi'
const InputAndButton = styled.div`
display: flex;
justify-content: space-between;
margin-top: 20px;
`
const InputName = styled.input`
font-size: 20px;
width: 100%;
height: 40px;
padding: 2px 7px;
`
const Button = styled.button`
font-size: 20px;
border: none;
border-radius: 3px;
margin-left: 10px;
padding: 2px 10px;
background: #1E90FF;
color: #fff;
text-align: center;
cursor: pointer;
${({ disabled }) => disabled && `
opacity: 0.5;
cursor: default;
`}
`
const Icon = styled.span`
display: flex;
align-items: center;
margin: 0 7px;
`
toast.configure()
function AddTodo() {
const initialTodoState = {
id: null,
name: "",
is_completed: false
}
// todo state変数名
// setTodo state変更関数名
const [todo, setTodo] = useState(initialTodoState)
// 入力欄に文字が入力されたら呼び出される関数
const handleInputChange = event => {
// カラムと値を定義
const { name, value } = event.target;
// スプレッド構文で展開しnameカラムを指定しvalueを更新
setTodo({ ...todo, [name]: value })
}
const notify = () => {
toast.success('Todo successfully created!', {
position: 'bottom-center',
hideProgressBar: true
})
}
const navigate = useNavigate()
const saveTodo = () => {
var data = {
name: todo.name
}
axios.post('/api/v1/todos', data)
.then(resp => {
setTodo({
id: resp.data.id,
name: resp.data.name,
is_completed: resp.data.is_completed
})
notify()
navigate('/todos')
})
.catch(e => {
console.log(e)
})
}
return (
<>
<h1>New Todo</h1>
<InputAndButton>
<InputName
type="text"
required
value={todo.name}
name="name"
onChange={handleInputChange}
/>
<Button
onClick={saveTodo}
disabled={(!todo.name || /^\s*$/.test(todo.name))}
>
<Icon>
<FiSend />
</Icon>
</Button>
</InputAndButton>
</>
)
}
export default AddTodo
各関数の役割
handleInputChange
入力欄に文字が入力されたら呼び出される関数です。setTodoによってnameカラムの値をvalueに更新しています。
…todoは、スプレッド構文といい以下のように展開されています。

saveTodo
ボタンをクリックした際に呼ばれる関数です。axiosによって非同期での通信を可能にしています。
そもそもaxiosとは、特定のエンドポイントへのリクエストを送信できるようにする、HTTP クライアントライブラリです。
今回は新しいデータを作成するため、POSTリクエストを送信しています。
送られている'/api/v1/todos'はコントローラーのcreateメソッドで、paramsの中にdataのハッシュ値を送っています。
def create
todo = Todo.new(todo_params)
if todo.save
render json: todo
else
render json: todo.errors, status: 422
end
end
デバックしてみるとparamsの中身はこのようになっています。
[1] pry(#<Api::V1::TodosController>)> params
=> #<ActionController::Parameters {"_json"=>{"name"=>"test"}, "controller"=>"api/v1/todos", "action"=>"create", "todo"=>{}} permitted: false>
ちゃんとnameが送られていますね。
なお、今回の変数nameはハッシュ構造で送っていますが、配列でも送ることが可能です。同時保存などをする際は利用できそうですね!
バックエンド側で保存できたらrenderでレスポンスを返しています。
レスポンスはこのようになっています。

基本的にdataを取り出して利用することが多いです。
このようにsaveTodoは、json形式でnameをparamsに含めて送り、データを保存、レスポンスを返す役割をもっています。
useStateを読み解いてみた まとめ
今回の記事ではフロントにReact、バックエンドにRailsを使いReact hookのuseStateを読み解いていきました。
1.useStateの使い方はuseState関数をインポート
import React, { useState } from 'react'
2.宣言
// todo state変数名
// setTodo state変更関数名
// initialTodoState 初期値
const [todo, setTodo] = useState(initialTodoState)
以上の手順で利用することができます。
ぜひ、参考にしてみてください!
