mapで広げたリストを検索でフィルターしたい
下のようなpersonsリストのデータを、mapを使って表示した後に、それぞれの名前でフィルター検索できるようにしたい。
const persons = [
{
name: 'Takeshi',
age: 18,
country: 'Japan',
},
{
name: 'Jackson',
age: 21,
country: 'America',
},
{
name: 'Bono',
age: 30,
country: 'Brazil',
},
];
const Filter = () => {
return (
{persons
.map((person) => (
<div key={person.name}>
<h2>Name: {person.name}</h2>
<p>Age: {person.age}</p>
<p>Country: {person.country}</p>
</div>
))}
</>
);
};
このままではただリストが表示されているだけなので、ここにuseStateと検索用のインプット欄を追加。
検索欄に入力された値が、filterValに保存されるようになります。
//useStateでインプットされた文字を管理する
const [filterVal, setFilterVal] = useState('');
return (
<>
<input
type='text'
placeholder='Search by name'
value={filterVal}
onChange={(e) => setFilterVal(e.target.value)}
/>
...
そして最後にpersonsをフィルターするコードを追加します。
.filter((person) => person.name.indexOf(filterVal) !== -1)
この文ではfilterメソッドを使用し、personリストのnameが、filterValの値(入力された値)と一致すればtrue、一致しなければ-1(false)を返すようになっています。
全体のコードはこのようになります
import { useState } from 'react';
const persons = [
{
name: 'Takeshi',
age: 18,
country: 'Japan',
},
{
name: 'Jackson',
age: 21,
country: 'America',
},
{
name: 'Bono',
age: 30,
country: 'Brazil',
},
];
const Filter = () => {
const [filterVal, setFilterVal] = useState('');
return (
<>
<input
type='text'
placeholder='Search by name'
value={filterVal}
onChange={(e) => setFilterVal(e.target.value)}
/>
{persons
.filter((person) => person.name.indexOf(filterVal) !== -1)
.map((person) => (
<div key={person.name}>
<h2>Name: {person.name}</h2>
<p>Age: {person.age}</p>
<p>Country: {person.country}</p>
</div>
))}
</>
);
};
export default Filter;
フィルター前とフィルター後でこのようになります。
検索の時に大文字小文字の区別をなくす
今のコードでは大文字と小文字を区別しているので仮に'takeshi'と入れたら何も表示されなくなります。
これを修正するにはtoLowerCase()を使います。
.filter((post) =>
post.name.toLowerCase().indexOf(filterVal.toLowerCase()) !== -1)
このようにpost.nameとfilterValを両方小文字に変換することで区別をなくすことができます。