목표
- useEffect()훅을 통해 data fetching 등 컴포넌트 렌더링 이후에 필요한 다양한 side effect(부수효과) 일으키기
- fetch() 함수를 사용해 API 호출하는 방법 익히기.
- Array.map() 함수를 통해 component 재활용 해보기.
- props 를 사용해 단방향(부모 컴포넌트 > 자식 컴포넌트)으로 데이터를 전달해보기.
- Array.filter() 를 통한 검색기능을 구현해보기. (위의 필수 옵션 구현 후 추가 구현 사항!)
2주동안 배웠던 리액트 기초 개념을 적용하고 응용해서 Monster라는 과제를 진행했다.
오늘이 1차 프로젝트 진행 전 마지막 주말인데, 멘토님이 주말 동안 새로운 기능을 익히기 보다는
Monster 과제를 지웠다 다시 설치하면서 따라 치는거 없이 스스로 외워 칠 수 있을 때까지 반복하랬다.
(최소 3번은 해보라고 했는데 지금 4번 정도 진행한 것 같다. 왜 다음날만 되면 늘 새로울까...?🤔)
Task 1
git clone repo주소
)npm install
Task 2
useEffect
fetch()
useState()
function Monsters() {
const [monsters, setMonsters] = useState([]);
// 데이터 로딩
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => setMonsters(data));
}, []);
//이하 코드 생략
Task 3
function Monsters() {
const [monsters, setMonsters] = useState([]);
const [userInput, setUserInput] = useState("");
// 데이터 로딩
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => setMonsters(data));
}, []);
return (
<div className="monsters">
<h1>몬스터 미니 프로젝트!</h1>
<CardList monsters={monsters} />
</div>
);
}
CardList.js
function CardList({ monsters }) {
console.log(monsters)
return (
<div className="cardList">
</div>
);
}
↓콘솔 창에서 확인하면 아래와 같이 뜨는 것을 확인할 수 있다.
Task 4
Array.map( )
사용CardList.js
파일에서 넘겨 받은 데이터를 기준으로 map()함수를 사용하여 <Card/>
컴포넌트를 리턴해준다.Card.js
에게 넘겨줘야하는 props 는 각 몬스터 객체의 id, name, email
이다.function CardList({ monsters }) {
return (
<div className="cardList">
{monsters.map((monster) => (
<Card
key={monster.id} //map함수를 쓸땐 고유의 key값을 부여할 것.
id={monster.id}
name={monster.name}
email={monster.email}
/>
))}
</div>
);
}
Task 5
Card.js
로 넘어가 넘겨받은 props를 이용하여 태그 안의 내용을 작성한다.
이미지 주소의 경우 카드마다 다른 이미지를 보여줘야 하므로 주소의 숫자
부분을 prop를 통해 넘겨받은 id
로 대체해준다.
function Card({ id, name, email }) {
return (
<div className="cardContainer">
<img
src={`https://robohash.org/${숫자}?set=set2&size=180x180`}
alt="monster"
/>
<h2>{name}</h2>
<p>{email}</p>
</div>
);
}
state와 props와 effect hook을 이용하여 아래와 같이 완성하였다.
Task 6 (Optional!)
더 나아가 상단 가운데에 보이는 검색창에 filter() 메소드
를 이용하여 Monster 검색 기능을 추가해보았다.
먼저 <SearchBox/>
에 props
로 넘겨줄 handleChange
메소드를 정의한다.
function Monsters() {
const [monsters, setMonsters] = useState([]);
const [userInput, setUserInput] = useState("");
...중간 생략
// SearchBox 에 props로 넘겨줄 handleChange 메소드 정의
const findMonster = (e) => {
const { value } = e.target;
setUserInput(value);
};
return (
<div className="monsters">
<h1>몬스터 미니 프로젝트!</h1>
<SearchBox handleChange={findMonster} />
<CardList monsters={monsters} />
</div>
);
}
monster 객체의 name
값이며, 사용자가 소문자로 검색할 것을 고려하여소문자로 바꾼 monster 객체의 name값
과 사용자가 검색 창에 입력한 userInput값
을 비교한다.filter()
가 반환하는 값을 변수에 저장 후 return 문 안에 있는 CardList에 props
로 전달한다.Monsters.js
function Monsters() {
const [monsters, setMonsters] = useState([]);
const [userInput, setUserInput] = useState("");
...중간 생략
// SearchBox 에 props로 넘겨줄 handleChange 메소드 정의
const findMonster = (e) => {
const { value } = e.target;
setUserInput(value);
};
const monsterFilter = monsters.filter(
(monster) =>
monster.name.toLowerCase().includes(userInput.toLowerCase())
);
return (
<div className="monsters">
<h1>몬스터 미니 프로젝트!</h1>
<SearchBox handleChange={findMonster} />
<CardList monsters={monsterFilter} /> //기존의 monsters 대신 filter가 반환하는 값을 넘겨준다.
</div>
);
}
검색창에 d를 입력하면 이름에 d가 포함되어 있는 몬스터들만 필터링되어 보여준다.🤗🤗