props(변수,함수 passing)하는 방법에 대해 알아보자
ajax는 제이쿼리용임으로 사용하지말고
순수한 fetch가 있고 다운받아서 쓰는 axios가 있는데
axios는 다운을 받아야한다
이말은 즉 fetch는 다운받지 않아도 사용가능하지만
가장 인기있는 axios는 따로 다운을 받아서 사용해야한다
우리가 무언가 받을 경우 http 요청을 하게 되는데
아직 받을 데이터는 없기에 임의로 데이터를 지정해보자
const [boards,setBoards] = useState([]);
이렇게 임의 데이터를 만들어서 쓸 수 있다
데이터를 받아올 경우 그 값을 컴포넌트에 쓰는 경우가 있는데
웬만하면 pages폴더를 만들고 그 안에 000pages 를
각각 알아보기 쉽게 만들고 그 안에 <000/> 이런식으로
header main footer 등등을 넣어주고
페이지안에 선언해주는게 좋다
왜냐하면 어디서 어떻게 쓸지 모르기도 하고
여기서도 필요하고 저기서도 필요할 수 있기 때문이다
만약 단 하나의 컴포넌트에서만! 필요하다면
그 안에 써주는것이 맞지만 그렇지 않으면 웬만하면 페이지에 적어주자
props를 passing한다는 것은
부모가 자식에게 데이터를 넘겨주는 것을 뜻한다
변수 즉 속성을 넘기는 것이다
HomePage.js라는 파일에서
DB로부터 데이터를 받아온다는 가정을 했을 때
현재는 데이터가 없기 때문에
가상의 데이터를 만들어보자
import React, {useEffect, useState} from 'react';
import Header from "../components/Header";
import Footer from "../components/Footer";
import Home from "../components/home/Home";
const HomePage = () => {
//http 요청 (jquery ajax, fetch)
//db가 없으니 임의로 만들자
const [boards,setBoards]=useState([]);
//빈 배열 한번만 실행
useEffect(()=>{
//다운로드 가정 = fetch(),axios(),ajax()
let data = [
{id : 1, title:'제목1',content:'내용1'},
{id : 2, title:'제목2',content:'내용2'},
{id : 3, title:'제목3',content:'내용3'},
];
//빈데이터가 다운로드가 되기전에 먼저 들어가버린다
//그리고 다운로드가 완료되면 콜백되어서 setBoards에 다시 데이터가 들어간다
setBoards([...data]);
},[]);
return (
<div>
<Header/>
<Home boards={boards}/>
{/*useEffect가 끝나면 우선 이곳에 빈데이터가 뿌려진다*/}
{/*위에 다운로드후 콜백이되면 상태변화가 생겨서 다시 그려지게된다*/}
{/*위에 setboards는 무조건 상태값이여야한다 그렇지않으면 다시 그려지지 않는다*/}
{/*위에 boards처럼 Home에 넘어간 데이터를 속성 즉 props라고 한다 */}
<Footer/>
</div>
);
};
export default HomePage;
위에 boards라는 배열변수를 만들어서 초기값에 [] 빈배열을 임의로 만든다
useEffect를 사용해주는데 끝에 , [] 를 넣어주면 최초 실행시 한번만
실행되게 해줄 수 있다
가상의 데이터를 만들기위해서
let data를 통해서
3개의 데이터를 만들어주고
그 데이터를 setBoards안에 전개연산자로 넣어준다
그 데이터를 우리는 Home에서 사용할 예정이니
이렇게 보내줄 수 있는데
이것이 바로 props를 사용해서 데이터를 자식에게 물려주는 것이라고 할 수있다
그림이 그려지면서
헤더
홈
푸터
순으로 그려질때 최초의 useEffect가 실행되면서
boards안에 빈데이터가 뿌려진다 왜냐하면 cpu연산속도를 메모리가 따라잡을 수 없기 때문이다
결국 빈데이터가 들어가도 다운로드후 그림을 다시그리기 때문에 데이터는 들어간다는 것을 알아야한다
우선 빈데이터가 뿌려진다음 위에서 데이터가 전부 다운로드가 되면 콜백이되어서
상태변화가 일어나서 그림을 처음부터 다시 그리게 된다
그렇게 상태변화가 일어나려면 무조건 setboards는 상태값이되어야하고
그렇지 않으면 상태변화가 생기지않기때문에 렌더링이 되어서 다시그려지는 것을 하지못하게되서
그림을 다시 그리지못한다
위에 boards처럼 Home에 넘기는 데이터를 속성 즉 props라고 부른다
여기서 가장 중요한 것은
boards는 상태값이어야한다
예를 들어
let bo = data;라고해서 위에서 받아온 데이터를
bo라는 곳에 담고
아래에
이런형태로 작성하면
let bo는 상태값이 아니기때문에 그림이 다시 그려지지 않아서
데이터를 읽어서 던질 수 없게된다
그러니 꼭 상태값으로 사용해야한다 (아래에 상태값에 대해 따로 정리해두었으니 참고하자)
자 그렇다면 이 던진 데이터를 Home에서 어떻게 받는지도 알아야한다
import React from 'react';
//function 방식
//class 방식
const Home = (props) => {
console.log(props);
return (
<div>
<h1>홈페이지입니다</h1>
</div>
);
};
export default Home;
위 코드에서 넘긴 데이터를 받으려면
(props) 대신 (boards)라고 써주면되는데
이런것을 function 방식으로 받은 것인데
만약 이것을 class 방식으로 받으려면 어떻게해야할까
요즘에는 잘 사용하지 않지만 그래도 알아두자
{this.props.boards} 라고
return 안에 적어주면 사용할 수 있는데
웬만해서는 불편하니까 편리한 function방식을 이용하는게 좋겠다
지금 boards만 넘기니까 (boards)라고 해주면 되는데
넘겨지는 데이터가 1개가 아니라 여러개일 경우 어떻게 해야할까?
바로 그냥 props만 적어주면 개수에 상관없이 다 받아올 수 있다
props로 바꿔주고 console.log를 통해서
데이터가 잘 넘어오는지 확인해보자
처음에는 빈 데이터가 넘어오고
이어서 던진 3개의 데이터가 0번지부터 2번지까지 정상적으로 넘어온다
우리가 던진건 boards밖에 없는데
이럴경우에 console에 props.boards를 써줘도 된다
props라고만 받아왔을 때와
props.boards라고 해서 받아왔을때의 차이는 이렇게 보여지는데
전부들고 오려면 props !
boards 하나만 들고오려면 props.boards를 해서 특정한 데이터만 넘겨받을 수 있다
확인을 위해서
const boards=props.boards;
console.log(boards);
이렇게 작성하고 새로고침을 하면
데이터가 정상적으로 넘어오는 것을 확인할 수 있다
자 이번에는 임의로 데이터를 2개를 넘겨보자
홈에 가상의 데이터 id={1} 이라고 던져서 총2개의 데이터를 넘길 경우
props에는 2개의 데이터가 담겨있을것이고
console.log(1,props);
라고 작성해서 출력해보면
이렇게 2개의 데이터가 잘 나오는 것을 볼 수 있다
그럼 실제로 코드를 짤 경우 여러개의 데이터를 어떻게 써야 효율적일까?
가장 편한 방법은 구조분할 할당이라는 것을 사용하는 것이다
우리는 boards와 id 2개의 데이터를 받았기 때문에
const{boards,id}= props;
보낼 때 boards로 보냈는데 여기서 board라고 쓰면 데이터를 못받아오니까
철자가 맞는지 꼭 확인해주는 것이 올바르다고 할 수 있다
이 새로운 문법을 구조분할 할당이라고 한다
id는 가짜 데이터이니까 일단 지워주자
이제 부모로부터 데이터를 받아왔으니 자식컴포넌트에서 그 데이터를 출력해보려고 한다
map을 이용해서 받아온 데이터를 뿌려보자
import React from 'react';
//function 방식
//class 방식
const Home = (props) => {
//구조분할 할당
const{boards}= props;
return (
<div>
<h1>홈페이지입니다</h1>
{boards.map((board)=><h3>
제목 : {board.title} 내용 : {board.content}
</h3>)}
</div>
);
};
export default Home;
이런식으로 뿌려주면
홈페이지입니다
제목 : 제목1 내용 : 내용1
제목 : 제목2 내용 : 내용2
제목 : 제목3 내용 : 내용3
이렇게 맵으로 출력이된다
이것이 바로 props라는 것이다
이것을 모르면 코딩을 할 수 없으니 꼭 이해해야한다
자 뿌려진 이 데이터의 주인은 Home.js가 아닌
HomePage.js이다
부모가 자식에게 props를 passing 즉 속성 변수를 패싱하는 것이다
프로퍼티를 넘기면 props로 받는 것이다
이번에는 받아온 boards 데이터를 전부 삭제하는 버튼을 하나 만들어보자
상태값을 변경하는 것이기 때문에 setboards를 빈배열로 만들어서
삭제할 수 있는데 그 데이터의 주인이 누구다?
Home.js가 아닌 HomePage.js이다 그렇기때문에 데이터를 넘겨받을 때
setBoards도 같이 넘겨받아야한다
이렇게 같이 넘겨주고
넘겼으니 받아줘야하는데
아까 설명했던 구조분할 할당을 통해 받으면 된다
const{boards,setBoards}= props;
이렇게 넘겨받은 후
버튼 onClick를 이용해서 데이터를 초기화 시켜주면! 전체삭제가 된다
<button onClick={()=>setBoards([])}>전체삭제
여기서 전체삭제 버튼을 눌러주면
이렇게 받아온 데이터가 전부 날라간다
데이터가 잘 날라갔는지 console.log로 찍어보고 전체삭제를 눌렀을 때
빈배열이 나오는지 확인해보는 것도 좋다
여기서 넘긴건 함수를 부모가 자식에게 패싱해서 넘긴 것이다
데이터 플로우를 정의하면
부모에서 자식으로 내려가는 플로우이다
그것을 거스르는 플로우는 존재 할 수 없다
A라는 부모페이지 안에 B,C라는 자식 컴포넌트가 있고
B에서는 데이터를 받아서 보여주고
C에서는 데이터를 삭제하는 버튼을만들어서 버튼을 누르면 B데이터를 날리고자 한다면
B는 데이터를 받고
C는 함수를 받아서 데이터를 컨트롤해야한다
B,C모두 A라는 부모로부터 받는것이지 역으로 부모에게 줄 수는 없다
이유는 부모가 품은 자식들이 있기에 부모가 그려지면서 그 안에 자식들도 그려지는 것이다
데이터를 받아서 보여주는곳은 변수를 넘기고
버튼쪽에는 함수를 넘긴다고 이해하면 된다
항상 부모에서 데이터를 받고 자식에게 뿌려주는 것을 기본으로 하는것이 유지관리에 좋다
만약 부모가 데이터를 가지고 있지 않고 그 부모안에
자식 컴포넌트가 2개가 있는데
A자식은 데이터를 가지고있고 그 데이터를 보여주고
B자식은 버튼을 가지고있고 그 버튼을 눌러서 A데이터를 날리고 싶다면
부모로부터 받아야하는데 데이터 주인이 부모가 아닌 A자식일 경우
B에서 A데이터를 컨트롤 할 권한이 없기 때문에 애초에 말이 안되는 구조이다
이런 상황때문에 컴포넌트 구조화가 중요한 것이다
하지만 이런 경우에도 사용할 수 있는 방법이 하나 있는데
그것이 Redux라는 라이브러리이다
자바에 ioc 컨테이너처럼 외부에 store를 만들고
어디서든 그것을 가져다 쓸 수 있도록 해주는 것이다
필요할 때 언제든 스토어에 접근하면되는데 이것은 나중에 따로 설명을 해보자
이렇게 정리한것을 토대로 작은 예시를 한번 숙제라고 생각하고 해보자
숙제는 Home.js에 0이라는 초기값을 넘기고
버튼을 하나 만들어서 해당 버튼을 클릭하면 숫자가 1씩 증가하도록 하는 것인데
HomePage.js에서 props를 이용해서 데이터를 넘기고 그 데이터 함수까지 넘겨서
데이터를 뿌리고 관리할 수 있도록한 상태에서 숫자를 증가하도록 하는 것이다
혹시 이 글을 보고 있다면 이렇게 나오도록 해보면 좋을 것 같다
<상태값에 대해서>
자 여기서 궁금한점은 상태값을 어떻게 사용하는지? 어떤게 상태값인지? 알아둘 필요가 있다
예전에는 없었지만 리액트가 업데이트되어가면서
리액트 16.8 이전 버전에서는 함수형 컴포넌트에서는 상태를 관리할 수 없었고
State, Life Cycle 등등 이 없기 떄문에 클래스형 컴포넌트를 사용해야만 했다
리액트 16.8버전 부터는 Hooks 라는 기능이 도입되면서
함수형 컴포넌트에서도 상태를 관리할 수 있게 되었다.
useState Hook을 사용하여 State 사용이 가능하게 되었는데
useState는 상태를 다를 수 있는 특별한 함수인데
import를 통해 useState를 사용할 준비를 해주고
function Test() {
import react, { useState } from 'react'
const [loginChecked,setLoginChecked] = useState(false);
}
이런식으로 불러와서 사용할 수 있다
useState를 호출하게되면 기본적으로 배열을 반환하는데
배열의 0번째 요소는 loginChecked이고 현재 state변수이다
배열의 1번째 요소는 setLoginChecked인데 이게 변수를 갱신할 수 있는 함수이다
useState의 인자로 넘겨주는 값은 초기값 false이다
간단하게 정리해보면
loginChecked : stats상태를 저장하는 함수
setLoginChecked : state상태를(loginChecked)를 변경하는 함수
useState: React Hook
false : State상태 초기값
이렇게 예시로 만든 것을 직접 사용하려면
JSX Element안에서 직접 불러서 사용해야 하는데
위 예시는 boolean true or false 여부에 따라 결과를 다르게 보여주기 때문에
삼항연산자를 이용해 볼 수 있다
<div>{loginChecked? "Checked!" : "unChecked"}</div>
로그인이 되어있으면 checked! : <-- 로그인이 되어있지 않으면 이라는 뜻으로
콜론을 이용해서unchecked를 보여주면된다
이번에는 상태를 변경해보고 싶다고 했을 때 어떻게 할지 알아보는데
앞서 말했던 상태변경 함수인 setLoginChecked를 호출해야 한다
import react, { useState } from 'react'
function Example() {
const [loginChecked, setLoginChecked] = useState(false);
const checkHandler = (e) => {
setLoginChecked(e.target.checked);
}
return (
<div>
<input type="checkbox" checked={loginChecked} onChange={checkHandler} />
<span>{loginChecked ? "Checked !" : "unChecked"}</span>
</div>
)
}
이 예시의 경우 input 태그의 JSX 엘리먼트 값 변경에 따라서 상태(loginChecked)가 변해야 한다 즉, 브라우저에서 체크박스가 체크되면 코드상에 상태(loginChecked)가 변경되야 한다는 뜻 이다
사용자가 체크박스 값을 변경하면 input 태그의 onChange 이벤트가 checkHandler 함수를 호출하고 이 함수가 상태변경 함수인 setLoginChecked 를 호출한다 그렇게 되면 결과에 따라 상태(LoginChecked)가 갱신되며, React는 갱신된 상태(LoginChecked)를 Test 컴포넌트에 넘겨 해당 컴포넌트를 다시 렌더링 한다.
'FrontEnd' 카테고리의 다른 글
라우팅하기, 부트스트랩 적용 (react router dom) (1) | 2022.11.16 |
---|---|
Styled Component props 패싱 개념정리 (0) | 2022.11.16 |
components styled 개념정리 (0) | 2022.11.16 |
useRef 개념정리 (0) | 2022.11.16 |
useMemo 개념정리 (0) | 2022.11.16 |