React入門第10回~filterメソッドを使ってみよう~

filterメソッドを使ってみよう

プロ太先生、filterって何ですか?配列の中身を絞り込むって聞いたことがあるんですが…。

filterは配列の中から条件に合った要素だけを取り出すためのメソッドですね。たとえば、リストの中で特定の文字が含まれているものだけを表示したいときに使えるんです。こんなコードを書いてみましょう。フィルターで動物の名前を絞り込む例です。

コード例1:動物リストをフィルターする

import { useState } from "react";

const animals = ["Tiger", "Lion", "Elephant"];
// POINT filterメソッドの使い方
const Example = () => {
  const [filterVal, setFilterVal] = useState("");

  return (
    <>
      <h3>配列のフィルター</h3>
      <input
        type="text"
        value={filterVal}
        onChange={(e) => setFilterVal(e.target.value)}
        placeholder="動物の名前を入力してみてね"
      />
      <ul>
        {animals
          .filter((animal) => animal.includes(filterVal))
          .map((animal) => (
            <li key={animal}>{animal}</li>
          ))}
      </ul>
    </>
  );
};

export default Example;

まずは、useStateを使ってfilterValという値を管理しています。このfilterValには、OZくんがテキストボックスに入力した値が常にセットされるんです。

なるほど、テキストボックスで入力した内容がそのままfilterValに入るんですね。

そうです。そして、animals.filter()を使って、各要素に対してfilterValが含まれているかどうかを確認しています。

{animals
.filter((animal) => animal.includes(filterVal))
の部分では、animalsの配列に対して、includesメソッドを使って、filterValがその配列の要素に含まれているかチェックしているんですね。

その通りです!そして、フィルターされた結果がmapメソッドでリストとして表示されるわけだね。じゃあ、ちょっと実行して、テキストボックスに『Ti』とか入力してみてくれる?

はい、やってみます!…おお、Tigerだけが出てきました!

次に、もう少し複雑なデータのフィルターを試してみましょう。今回は人のプロフィールをフィルターします。

import Profile from "./components/Profile";
import { useState } from "react";

const persons = [
  {
    name: "Alex",
    age: 20,
    hobbies: ["swimming", "reading"],
  },
  {
    name: "Bella",
    age: 25,
    hobbies: ["cooking", "painting"],
  },
  {
    name: "Chris",
    age: 18,
    hobbies: ["gaming", "music", "hiking"],
  },
];

const Example = () => {
  const [filterVal, setFilterVal] = useState("");

  return (
    <>
      <input
        type="text"
        value={filterVal}
        onChange={(e) => setFilterVal(e.target.value)}
        placeholder="名前を入力してみてね"
      />
      <ul>
        {persons
          .filter((person) => person.name.includes(filterVal))
          .map((person) => (
            <li key={person.name}>
              <Profile {...person} />
            </li>
          ))}
      </ul>
    </>
  );
};

export default Sample;

このProfileコンポーネントは何をしているんですか?

このProfileコンポーネントが人物のプロフィールを表示してくれるんです。詳細をコードで確認してみましょう。

const Profile = ({ name, age, hobbies }) => {
  return (
    <div>
      <hr />
      <div>名前: {name}</div>
      <div>年齢: {age}</div>
      <div>
        <div>趣味:</div>
        <ul>
          {hobbies.map((hobby) => (
            <li key={hobby}>{hobby}</li>
          ))}
        </ul>
      </div>
    </div>
  );
};

export default Profile;

それじゃあ、まず、Sample.jsxファイルの、人物リストpersonsのフィルター部分を詳しく解説していきますね。以下の部分です。filterメソッドについては解説済みですが、復習しておきましょう!

 <ul>
        {persons
          .filter((person) => person.name.includes(filterVal))
          .map((person) => (
            <li key={person.name}>
              <Profile {...person} />
            </li>
          ))}
      </ul>

コード解説

  1. persons.filter()の部分
    • filterメソッドは配列personsの各要素(ここではperson)を順にチェックして、特定の条件に合う要素だけを新しい配列にまとめます。
    • 条件としては、person.name.includes(filterVal)trueのときだけそのpersonをフィルター結果に含めます。
    • includesメソッドは、文字列の中に指定した文字が含まれているかを確認します。この場合、filterValの文字がperson.nameに含まれているかどうかをチェックしています。
  2. mapメソッドでリストを表示
    • フィルターで条件に合った人物の配列を得た後、その配列の各要素を<li>タグでリスト表示します。
    • personのデータをProfileコンポーネントに渡して表示するために、<Profile {...person} />と書かれています。これはスプレッド構文を使って、personオブジェクトの中身をProfileコンポーネントに渡しています。
      この{...person}は、personオブジェクトの中にあるすべてのプロパティ(例えば、nameagehobbies)を展開して、それぞれをProfileに一括で渡すという意味です。これで、Profileコンポーネントの中では、nameagehobbiesが個別のプロパティとして扱えるようになります。スプレッド構文を使わずに一つずつ渡すとしたら、以下のような感じになります。
<Profile name={person.name} age={person.age} hobbies={person.hobbies} />

personオブジェクトにさらにaddressjobといった新しいプロパティが追加された場合、それぞれを追加で書き込む必要が出てきますが、スプレッド構文を使えば、オブジェクトの中身をまとめて展開できるから便利です。

3.key属性の追加

  • Reactでは、リスト表示を行うときにkey属性を指定することが推奨されています。ここでは、key={person.name}として、各人物のnamekeyに使っています。
  • keyはReactが各要素を識別するためのものなので、重複しない値(ユニークな値)である必要があります。

なるほど!filtermapが連携して、入力した名前に応じた人物だけがリストに表示されるんですね。

その通り!そして、Profileコンポーネントに人物のデータを渡して、個別に表示するようにしているんです。

次に気になるのがhobbiesの部分です。趣味のリストがどうやって表示されるのか教えてください!以下の部分です。

<ul>
  {hobbies.map((hobby) => (
    <li key={hobby}>{hobby}</li>
  ))}
</ul>

コード解説

  1. mapメソッド
    • mapメソッドは配列の各要素を順に処理し、処理結果を新しい配列として返します。この場合、hobbies配列の各hobbyをリスト形式で表示しています。
    • hobbies.map((hobby) => ( ... ))では、hobbyhobbies配列の各要素を順番に受け取って処理します。
  2. <li key={hobby}>{hobby}</li>タグ
    • <li>タグの中に各hobbyの内容が表示されます。これにより、趣味がリスト形式で一つずつ表示されるようになります。
    • key属性にはhobby自体を指定しています。hobbyがユニークであることが前提ですが、同じ趣味が含まれる場合には異なるキーを用意するか、他の値を使うことを検討する必要があります。

mapを使うことで配列の各要素を一つずつ表示できるんですね!これで趣味がリストとして表示されるわけですね。

その通り!そして、Profileコンポーネントの中では、hobbiesという配列を受け取って、趣味を一覧表示しているんだ。このようにコンポーネントの中でmapを使えば、配列データを簡単にリスト表示できるようになりますよ!

補足:filterメソッド第2引数・第3引数のReactでの使い方

filter メソッドの第2引数に渡すのは、各要素に対して呼び出されるコールバック関数 です。このコールバック関数は、以下の3つの引数を取ることができます。

  • element: 現在の配列要素
  • index: 現在の要素のインデックス
  • array: 配列全体

つまり、上記3つのどれかでしぼっていくことができるということです!!

コールバック関数の役割

コールバック関数は、各要素に対して実行され、その戻り値が true の場合に、その要素が新しい配列に含まれます。つまり、条件を満たす要素だけを抽出する 働きをします。

第1引数の活用例

const numbers = [1, 2, 3, 4, 5];

// 偶数のみを抽出
const evenNumbers = numbers.filter(function(element) {
  return element % 2 === 0;
});

console.log(evenNumbers); // [2, 4]

この例では、filter メソッドのコールバック関数で、要素が偶数かどうかを判定しています。偶数の場合に true を返し、新しい配列 evenNumbers に追加されます。

第2引数の活用例

const words = ['apple', 'banana', 'cherry', 'date'];

// インデックスが偶数の要素のみを抽出
const evenIndexWords = words.filter((_, index) => {
  return index % 2 === 0;
});

console.log(evenIndexWords); // ['apple', 'cherry']

この例では、_ で要素の値は無視し、index を使ってインデックスが偶数の要素だけを抽出しています。

第3引数 (array) の活用例

const numbers = [1, 2, 3, 2, 1];

// 重複する要素を除去
const uniqueNumbers = numbers.filter((element, index, array) => {
  return array.indexOf(element) === index;
});

console.log(uniqueNumbers); // [1, 2, 3]

この例では、array.indexOf(element) で、要素が初めて現れるインデックスを取得し、それが現在のインデックスと一致する場合にのみ、その要素を新しい配列に追加しています。これにより、重複する要素を除去することができます。

まとめ

今日の授業内容で、配列のフィルターと表示のやり方が分かりました!実際にコードを書きながらやってみます!

それが一番ですね!Reactの基本操作は慣れると応用が効くから、どんどん試してみましょう!

このように、リストのフィルターと配列の表示を学ぶことで、データを動的に管理し表示する方法を理解できたかと思います。さらに実践で応用しながら身に着けていきましょう!