
조건을 만족한 값을 새로운 배열로 리턴한다.
기본 Syntax
const words = ['Ryan','Kookie','Niniz','Appeach','V','BabyJordib'];
const result = words.filter(word=> word.length > 5);
console.log(result);
//['Appeach','BabyJordib']
앞으로 우리가 많이 사용할 배열 & 객체형식으로 연습해보자
const todos = [
{
id: 1,
text: "eating",
done: true
},
{
id: 2,
text: "sleeping",
done: true
},
{
id: 3,
text: "stuyding",
done: true
},
{
id: 4,
text: "cooking",
done: false
}
];
만약 위의 배열에서 done 값이 false을 가진 배열의 원소 오브젝트를 배열로 가져오고 싶다면,
즉 {
id: 4,
text: "cooking",
done: false
}
을 가져오고 싶다면,
const notDone = todos.filter(todo => todo.done === false);
console.log(notDone);
// (1) [Object]
0 : Object
id : 4
text: "cooking"
done: false
객체를 배열에 담아 리턴한 것을 볼 수 있다.
조건식은 (todo => !todo.done) 로 바꿔줄 수 있다.
배열안에 여러개의 객체가 있는데, 배열을 담은 변수이름에 접근하여 key값을 dot notation을 통해 바로 값을 구할 수 있다는 것이 편리한 듯하다.
나는 여기서 왜 시간을 쏟았는가...
filter 개념을 토대로 monster 과제의 검색창에 일치하는 이름의 몬스터카드를 반환하는 기능을 추가 구현해 보았는데,
여기서 검색대상(비교대상)은 monster 객체의 name이다.
미리 주어진 배열인 monster의 url 주소를 브라우저에 입력해보니,
배열안의 객체 형식으로 잘 들어와있는 것을 볼 수 있었다.
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna@melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
..생략},
Logic Steps
1번을 작성하기 위해서는 먼저 input box가 onChange될 때마다 값을 받아와주는 handleChange라는 함수를 작성하였고, 호출 시 인자로 들어오는 이벤트객체(e)를 활용해 userInput 으로 setState를 설정해 주었다.
handleChange = (e) => {
this.setState({
userInput: e.target.value,
});
};
또한 monster, userInput 과 handleChange는 컴포넌트에 이용해야 하므로 비구조할당을 이용하여 변수에 묶어주고 함수식을 작성하였다. 대소문자의 경우가 없어야하고, value값을 포함하는 것을 filter 해야하므로
const filterNames = monsters.filter((monsters) => {
return monsters.name.toLowerCase().includes(userInput);
});
arrow function 특성상 인자의 괄호는 생략가능하고, 식을 간략하게 작성할 수 있을 경우(함수를 다시 받는다던지x) return key word도 생략 가능하다.
기존에 부모 컴포넌트에 props 값으로 전달해주었던 컴포넌트에 monsters props 값을 삭제하고 변경해주니 정상적으로 작동하는 것을 볼 수 있었다.
<CardList filterNames={filterNames} />;
변수에 저장한 filter 로 나온 결과값들을 props로 전달해서 다시 map 을 돌려 출력한다는 개념은 이해를 하였다. 하지만 기존에 있던 monsters.map은?
처음에는 monsters 도 map을 돌려야하고, filterNames도 각각 map 을 돌려야하므로 식을 따로 작성해줘야하지 않나 생각했다. 하지만 filterNames는 input이 Onchange 될 때만 실행되고 값을 반환하므로 내가 입력창에 값을 입력하지 않은 이상, 초기값은 모든 monsters들이 화면에 출력된 것을 볼 수 있다.
<div className="card-list">
{filterNames.map((filterNames) => (
<Card
key={filterNames.id}
id={filterNames.id}
name={filterNames.name}
email={filterNames.email}
/>
))}
</div>
);
추가
filter 함수는 callback 함수를 호출하여 만들 수도 있다
const snacks = ['chips','cookies','gum','macaroon','cherry']
function checkSnacks = (str) => {
return snacks.filter((el) => {
return el.toLoswerCase().indexOf(str.toLoswerCase()) >-1;
})
}
console.log(checkSnacks('ch'));
//['chips','cherry']