음... 강의를 들은 내 상황
리액트 알았죠?
아니요.
아 알았는데?
아니요 그냥 몰라요
익숙하다 싶으면 갑자기 때려맞는 리액트... 과제가 두렵지만 일단 배운 내용부터 정리해보자....
Props
지난 포스팅에서 정리했던 컴포넌트! 기억나는가?! 이 컴포넌트들을 이어주는 통로라고 생각하면 된다.
더 자세히 정리하면 부모컴포넌트가 자식컴포넌트에게 물려주는 데이터이다.
⭐️ 반드시 위에서 아래 방향으로!
즉, 부모 -> 자식 방향으로만 흐른다는 걸 명심하자 (자식 -> 부모는 안됨!)
그러면 부모 컴포넌트는 어떻게 props
를 통해 데이터를 전달할 수 있는지 코드를 보면서 살펴보자
현재 코드에는 App
이라는 상위컴포넌트 아래에 GrandFather
, Mother
, Child
3개의 자식컴포넌트가 있다.
Mother
컴포넌트에 있는 데이터를 Child
컴포넌트에게 전달해주려고 한다.
👩🏻💻 풀이
key
와 value
를 적어준다. (>> 데이터 줄거야~! 하는 느낌!)props
라는 매개변수를 받는다.props
로 전달받은 lastName
을 Child 컴포넌트
가 렌더링해서 출력한다.부모컴포넌트로부터 받은 props
를 콘솔창으로 확인해보면 lastName
과 그에 따른 value
가 객체형태로 들어간 걸 확인할 수 있다.
객체로 들어가 있으므로 우리는 자바스크립트때처럼 .key값
으로 접근할 수 있다!
수업 때 배운 이 코드를 보면 계속해서 props.name
으로 데이터를 전달하는 걸 볼 수 있다. 이렇게 계속해서 내려주고 내려주고 하는걸 드릴로 파고든다고 해서 prop drilling
이라고 하는데 딱 봐도 이걸 지양해야한다는 느낌이 팍팍 든다.
function Todo(props){
return <div>{props.todo}</div>
}
prop drilling
에서도 보았고, 위 코드처럼 지금까지 데이터를 전달받을 때마다 자식컴포넌트에서 props.name
을 적어주었다.
몇 번 안 적을 때는 크게 불편함이 없지만 이걸 몇 개나 반복해야하고, props
안에 많은 데이터가 들어있다면 사용하기 어려울 것이다.
때문에 우리는 자바스크립트에서 배웠던 구조분해할당을 활용해 효율적으로 데이터를 전달받을 수 있다.
👩🏻💻 구조분해 할당 적용한 코드
function Todo({ title }){
return <div>{title}</div>
}
// 여러개 props 받을 경우
function Todo({ title, body, isDone, id }){
return <div>{title}</div>
}
부모컴포넌트에서 깜빡하고 지정을 안 해주는 실수가 생겼을 때 사용할 수 있는 디폴트 값을 지정하는 방법이다.
자주 쓰이지 않지만 이런 것도 있구나 하고 이해하자!
children
은 또 뭐야! 부모컴포넌트가 자식컴포넌트에 접근하는 또 다른 방법이다.
children
도 똑같이 props
인데 방식이 조금 다른 것 뿐이다!
이 코드를 보면 부모컴포넌트는 App
, 자식컴포넌트는 User
로 되어있다.
App
안에 있는 User
컴포넌트에 "안녕하세요"라고 적어두고 콘솔로 User
의 props
와 출력화면을 보면 아래처럼 보인다.
콘솔에는 props
객체 안에 children
이라는 key
값이 들어있는 걸 볼 수 있다. 하지만 출력화면에는 "안녕하세요" 값이 보이지 않는다.
children
이라는 키 값으로 접근할 수 있고 children
도 똑같이 props
이므로 User 컴포넌트
에 props
와 전달할 데이터를 이렇게 표기해주면
우리가 원하는 "안녕하세요"까지 잘 렌더링 된 걸 볼 수 있다.
여기서 드는 의문점. 어차피 똑같은 props
이고 데이터를 전달하고 받는거라면 왜 굳이 children
을 써야할까? 싶었다. 그래서 주로 어떨 때 사용하는지 간단하게 정리해보았다.
👩🏻💻 Layout 컴포넌트를 만들 때 주로 사용
// src/About.jsx
import React from "react";
import Layout from "./components/Layout";
function App() {
return (
<Layout>
<div>여긴 App의 컨텐츠가 들어갑니다.</div>
</Layout>
);
}
export default App;
레이아웃처럼 자주 변하지 않고 동일한 형태를 여기저기 쓰는 것이라면 children
으로 만들어서 사용하면 편리하고 렌더링에도 도움이 된다.
// src/About.jsx
import React from "react";
import Layout from "./components/Layout";
function About() {
return (
<Layout>
<div>여긴 About의 컨텐츠가 들어갑니다.</div>
</Layout>
);
}
export default About;
앞에서 만든 컴포넌트를 props
로 전달해서 여러페이지에서 동일한 형태를 볼 수 있다.
State
리액트의 꽃🌸 state
!는 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.
state
를 만들때는 반드시 useState()
를 사용한다.
그리고 맨 위에 {useState}
를 써서 import
까지 해주어야 정상적으로 작동한다.
👩🏻💻 사용방법
const [ value, setValue ] = useState( 초기값 );
배열구조분해 할당을 사용해서 만들 수 있다.
value
: state의 이름setValue
: state를 변경시킬 값초기값
: 0을 적으면 맨 처음 state의 값은 0이 되고, ""을 적으면 공백이 된다.💡 setValue
를 이용해서 state
값을 변경시키면 적용된 컴포넌트는 화면에 리렌더링 된다.
import React, { useState } from "react";
function App() {
const [name, setName] = useState("길동이");
function onClickHandler() {
setName("누렁이");
}
return (
<div>
{name}
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
만약에 이렇게 name
의 초기값이 "길동이"로 설정된 state
를 만들었다고 치자.
그리고 버튼을 클릭하면 "누렁이"로 바꾸는 코드이다.
state
를 사용할 때 주의해야할 부분은 바로 "불변성"을 지켜주는 것인데, 배열의 데이터를 직접 수정하지 않고 전개연산자를 통해 복사한 배열의 값을 변경하여 사용하는 방식으로 해야한다.
⭐️ map, filter 메소드를 잘 사용할 수 있어야하는게 중요하다! (push 같은 원본 배열 값을 변경시키는건 쓰지 말자!)
예시
import React, { useState } from "react";
function App() {
const [dogs, setDogs] = useState(["말티즈"]);
function onClickHandler() {
// spread operator(전개 연산자)를 이용해서 dogs를 복사 후 항목 추가
setDogs([...dogs, "시고르자브르종"]);
}
console.log(dogs);
return (
<div>
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
우리가 자바스크립트에서 rest
라던가 전개연산자
를 배웠던 이유가 리액트에서 나타난다. 이렇게 원본 배열을 촥~ 펼친 후 그 뒤에 추가할 데이터를 적어줘서 안전하게 수정하도록 해야한다.
⭐️ 기억하자!
1. 새 배열을 만들어 기존 항목 복사하기! (전개연산자, map, filter 메소드 사용)
2. 복사한 배열을 가지고 추가 및 삭제하기!
아직 알랑말랑하지만 나머지는 개인과제하면서 익혀봅쉬다 🔥