24
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Reactで親コンポーネントのstateを下位のコンポーネントのイベント処理で更新する

Last updated at Posted at 2020-03-07

React で親コンポーネントの state を下位のコンポーネントのイベント処理で更新する

概要

 親コンポーネントで state を管理しているが、input 要素などの子コンポーネント側でイベント処理を行いたい時があると思います。結論から言うと、この場合の解決策の1つとしては、**「親コンポーネントから props 経由でハンドラー関数を渡す」**というやり方があります。気づけばカンタンなことですが、自分はハマってしまったので、誰かの参考になればと思って投稿しました。なお、React 初心者のため、もっと良い解決策がありましたら、ご教授ください。

本題

親コンポーネント Parent

Parent.js
import React, { useState } from 'react';
import Child from './Child.js';

function Parent() {
  // hook's state administration
  const [inputText, setInputText] = useState("");
  // handler function
  function handleInputTextChange(text) {
    setInputText(text);
  }

  return (
    <div className="App">
      <div className="Searcher">
        //!important->
        <Child handleInputTextChange={e => handleInputTextChange(e)}/>
        //<-!imoprtant
      </div>
      // display 'inputText' contents
      <p>{inputText}</p>
    </div>
  );
}

子コンポーネント Child

Child.js
import React from 'react';
import Paper from '@material-ui/core/Paper';
import InputBase from '@material-ui/core/InputBase';
import SearchIcon from '@material-ui/icons/Search';
import IconButton from '@material-ui/core/IconButton';

function Child() {
  return (
    <Paper component="form">
      <InputBase
        //!important->
        onChange={(e) => props.handleInputTextChange(e.target.value)}
        //<-!imoprtant
      />
      <IconButton type="submit">
        <SearchIcon />
      </IconButton>
    </Paper>
  );
}

export default Child;

 親コンポーネント Parent と子コンポーネント Child を示しました。

 今回の例では、Child にテキスト入力部分 InputeBase があり、そのテキスト入力の state を inputText という変数で、Parent において保持します。テキストの変化は、 handleInputTextChange というハンドラー関数で制御します。そして、 ParentinputText の内容を表示しています。挙動は以下のようになります。

ポイント

 今回の解説のポイントは、**「親コンポーネントからprops経由でハンドラー関数を渡す」**ことです。注意すべき点は以下の2点です。

  1. Parent では、<Child handleInputTextChange={e => handleInputTextChange(e)}/> のように、Child において制御する関数を Child の属性として渡すこと

  2. Child では props.handleInputTextChange(e.target.value) のように Parent から受け取る関数の前に props をつけること

です。

 どうしてこのようなことが必要になってくるのかというと、React では、制御されたコンポーネントの考えに基づき、親要素で state を管理することが一般的です。そこで state の管理もハンドラー関数も親要素で管理するとなりますが、その制御関数を子要素に渡すことができないとなると、親要素のファイル上で子要素を定義せざるを得なくなり、コードの量が増えてシンプルではありません。そこで、こういうときは props 経由で関数を渡すと良いと思います。もちろん、親子の階層構造がもっと複雑になった場合、state を一箇所で管理する Redux の導入も考えられるでしょうが、カンタンなものを作るだけであればこれで十分ではないでしょうか?

挙動

コードの解説

  1. ユーザーが入力するテキストが変化すると、子コンポーネント ChildinputBaseonChange が発火します。

  2. onChange に指定された関数 props.handleInputTextChangeParent から props 経由で渡されたものですが、Parent における handleInputTextChange の定義により、ここで setInputText によりstate である inputText が更新されます。

  3. state が更新されたことを受けて React の DOM ツリーが再描画され、Parent<p>inputText</p> 部分が書き換えられます。

UI

 UI上の挙動は以下のようになります。 テキストの入力に合わせて、テキストの下に表示されるp要素の内容が変化します。

スクリーンショット 2020-02-15 1.40.38.png スクリーンショット 2020-02-15 1.41.15.png

 以上です。いいねしてね。

24
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?