리액트 기초, Monster 과제 (react, fetch, Props, State, useEffect, map, filter)

라용·2022년 9월 13일
0

위코드 - 스터디로그

목록 보기
40/100

위코드 파운데이션 과정을 들으며 정리한 내용입니다.

기본 세팅

바탕화면으로 이동한 후 깃 클론으로 프로젝트 파일을 받고, 기록된 패키지들을 설치합니다.
git clone [레파지토리 주소] - 프로젝트 파일 내려받기
npm install - pakage.json 에 기록된 패키지들 설치
npm start - 파일 동작 확인

useEffect, fetch 메서드 활용 API 주소로 데이터 로딩

데이터 로딩은 첫 렌더링 때 한번만 실행되도록 useEffect 를 사용하고, 의존성 배열을 비워둡니다.

useEffect(() => {
	fetch( 'api 주소', {
		method: 'GET'
	})
}, [])

이때 method: 'GET' 은 생략 가능하고 응답값을 콘솔로 찍어볼 수 있습니다.

useEffect(() => {
	fetch( 'api 주소' )
	.then(( res ) => console.log(res))
}, [])

응답이 확인 되면, json 데이터를 js 로 변환하고 들어온 데이터를 State 에 저장합니다.

useEffect(() => {
	fetch( 'api 주소' ) // 데이터 가져와서
	.then(( res ) => res.json()) // json 데이터를 js 로 변경하고
	.then(( result ) => setMonsters(result)) // 위에 선언한 state 에 저장
}, [])

최상단에 아래와 같은 State 가 선언된 상태

const [monsters, setMonsters] = useState([]);

저장한 데이터 Props 로 전달, map 함수로 반복되는 컴포넌트 그리기

자식 컴포넌트에게 Props 방식으로 데이터를 전달하고

<CardList monsters={monsters} />

자식 컴포넌트는 Props 를 받습니다. 우선 데이터가 받아지는지 콘솔을 찍어 확인합니다.

function CardList(monsters) {
	console.log(monsters);
	return ();
}

이제 CardList 컴포넌트가 받은 Props 데이터로 map 메서드를 돌려 Card 컴포넌트를 생성합니다. (데이터 수 만큼) Props 데이터는 구조분해할당으로 객체 형태로 받습니다.

function CardList({ monsters }) {
	return (
		<div className="cardList">
			{monsters.map((monster)=>{
				return (
					<Card 
						// 객체의 key 값으로, value 에 해당하는 값 전달
						key={monster.id} 
						id={monster.id}
						name={monster.name}
						email={monster.email}
					/>
				);
			})}
		</div>
	);
}

이제 Card 컴포넌트가 데이터를 받아서 해당 카드 이미지를 그려줍니다. 구조분해할당으로 id, name, email 에 해당하는 value 값을 바로 사용합니다. 이미지 주소는 중간 숫자만 1, 2, 3.. 순으로 바꾸는 것이므로,(id 값으로 넣어줌) 백틱을 활용한 템플릿 리터럴과 달러를 활용해서 넣어줍니다.

function Card({ id, name, email }) { 
	return (
		<div className="cardContainer">
			<img src={`이미지주소${숫자}이미주소`} alt="" />
			<h2>{name}</h2>
			<p>{email}</p>
		</div>
	);
}

filter 메소드 활용, 필터링 로직 구현

서치박스에 입력하는 값과 monster 객채의 name 값을 비교해서 filter 메서드가 반환하는 새로운 배열의 값을 CardList 컴포넌트에 전달합니다. 서치박스가 아래와 같이 onChange 속성으로 Props 데이터를 받을 때,

function SearchBox(props) {
	return (
		<input 
			className="search"
			type="search"
			placeholder="Search..."
			onChange={props.handleChange}  // 입력 값 받기 위해서
		/>
	);
}

부모 컴포넌트에서 전달하는 함수를 만들어 줍니다.

// 이렇게 프롭스를 전달한다고 할 때
<SearchBox handleChange={updateUserInput} />

// 최상단에 이렇게 state 가 선언되어 있다면
const [userInput, setUserInput] = useState("");

// updateUserInput 함수를 작성하면
const updateUserInput = (e) => {
	setUserInput(e.target.value);
}

userInput 이란 state 에 유저가 입력하는 값을 저장했다면 이 값과 기존 monster 의 name 을 비교해서 일치하는 것이 있을 때 반환하는 필터링을 진행합니다.

const sortedMonsters = monsters.filter((monster)=>{
	return monster.name.includes(userInput);
});

filter 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열을 반환합니다. 이때 입력하는 값과 기존 몬스터 이름의 대소문자가 다르면 인식을 못하기 때문에 소문자로 변환하는 toLowerCase() 메서드를 사용합니다.

const sortedMonsters = monsters.filter((monster)=>{
	return monster.name.toLowerCase().includes(userInput.toLowerCase());
});

이제 필터링 된 sortedMonsters 데이터를 CardList 에게 전달합니다. 그럼 화면에는 검색에 기반해 일치하는 카드만 보여지게 됩니다.

<CardList monsters={sortedMonsters} />
profile
Today I Learned

0개의 댓글