React 데이터 흐름에 대해 다시 알아보자.
-react는 컴포넌트 단위다.
-상향식으로 만든다. (테스트가 쉽고, 확장성이 좋다)
-컴포넌트는 컴포넌트 바깥에서 props를 이용해 데이터를 마치 전달인자혹은 속성처럼 전달받을 수 있다.
-데이터를 전달하는 주체는 부모 컴포넌트다. (데이터 흐름이 하향식이다./ 단방향 데이터 흐름)
-컴포넌트는 props를 통해 전달받은 데이터가 어디서 왔는지 모른다.
-사용자 입력은 이벤트에 따라 변할 수 있다 (state)
-만일 하나의 상태가 두 컴포넌트의 영향을 받는다면, 공동 컴포넌트를 찾아 그곳에 위치시킨다.
-부모 컴포넌트에서의 상태가 하위 컴포넌트에 의해 변한다.
-하위 컴포넌트에서의 클릭 이벤트가, 부모의 상태를 바꾼다.
-상태를 변경시키는 함수를 하위 컴포넌트에 props로 전달해서 해결할 수 있다.
-하위 컴포넌트는 상위 컴포넌트로부터 전달받는 데이터의 타입이 무엇인지만 알 수 있다. 데이터가 state로부터 왔는지, 하드코딩으로 입력한 내용인지는 알지 못한다.
-상위 컴포넌트의 상태를 변경하는 함수 그 자체를 하위 컴포넌트로 전달하고 이 함수를 하위 컴포넌트가 실행한다.
예제1)
: 상태를 변경하는 함수는 handleChangeValue이고, 전달은 props를 이용하자.
props이름은,, 하위 컴포넌트가 버튼 클릭 이벤트에 따라 상태를 변경하려고 하므로 이름은 handleButtonClick 이다.
import React, {useState} from 'react';
export default function ParentComponent(){
const [value, setValue] = useState("날 바꿔봐");
const handleChangeValue = () =>{
setValue("보여줄게 달라진 값")
};
return (
<div>
<div>값은 {value}입니다 </div>
<ChildComponent handleButtonClick={handleChangeValue}/>
</div>
);
}
function ChildComponent({handleButtonClick}){
const handleClick = () =>{
handleButtonClick()
};
return <button onClick={handleClick}>값 변경</button>;
}
여러 컴포넌트 사이에서 어떤 방식들로 데이터를 다룰지 배워보자.
Effect Hook과 Ajax를 사용해 서버로부터 데이터를 받아오는 방법에 대해 배우자.
보통 React 애플리케이션 작성할때, AJAX 요청이 필요하거나,fetch API, LocalStorage, 타이머(setTimeout)와 같은 api를 사용하는 경우가 발생할 수 있다. 이것들은 Side Effect이며, 이를 다루기 위해 Effect Hook 을 제공한다.
순수함수란, 오직 함수의 입력만이 함수의 결과에 영향을 주는 것. 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 것은 순수함수가 아니다.
useEffect는 컴포넌트 내에서 Side effect 를 실행할 수 있게 하는 Hook이다.
useEffect의 첫번째 인자는 함수다. 해당 함수 내에서 sideEffect를 실행하면 된다.
sideEffect는 언제 실행될까?
useEffect(() => {
console.log(몇 번 호출될까요?)
})
//컴포넌트가 처음 생성되거나, props가 업데이트 되거나, state가 업데이트 될 때마다 실행됩니다.
useEffect(() => {
console.log(몇 번 호출될까요?)
},[])
//컴포넌트가 처음 생성될 때만 함수가 실행됩니다.
useEffect(() => {
console.log(몇 번 호출될까요?)
},[dep])
//dep이 업데이트 될 때마다 실행됩니다.
Hook을 쓸 때 주의할 점
useEffect의 두번째 인자는 '배열'이다. (종속성 배열이라고 한다.)
이 배열의 조건은 '어떤 값의 변경이 일어날 때'이다.
따라서 밑 예시에서 해당 배열엔 '어떤 값'의 목록이 들어간다.
이 예제는 filter가 변할 때에만, effect 함수가 실행된다.
한편, 카운트를 올리는 버튼은 아무리 눌러도 effect함수가 실행되지 않는다.
왜냐? 종속성배열에 filter만 존재하고 count는 존재하지 않기 때문이다.
이정도 코드는 외우는게 좋을 것 같다!!
import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";
export default function App() {
const [proverbs, setProverbs] = useState([]);
const [filter, setFilter] = useState("");
const [count, setCount] = useState(0);
useEffect(() => {
console.log("언제 effect 함수가 불릴까요?");
const result = getProverbs(filter);
setProverbs(result);
}, [filter]);
const handleChange = (e) => {
setFilter(e.target.value);
};
const handleCounterClick = () => {
setCount(count + 1);
};
return (
<div className="App">
필터
<input type="text" value={filter} onChange={handleChange} />
<ul>
{proverbs.map((prvb, i) => (
<Proverb saying={prvb} key={i} />
))}
</ul>
<button onClick={handleCounterClick}>카운터 값: {count}</button>
</div>
);
}
function Proverb({ saying }) {
return <li>{saying}</li>;
}
useEffect(함수,[종속성1, 종송석2,...])
useEffect 의 두번째 인자는 종속성 배열이다. 배열 내의 종속성1, 또는 종속성2의 값이 변할 때 , 첫번째 인자의 하수가 실행된다.
배열 내의 어떤 값이 변할 때만, effect가 발생하는 함수가 실행된다.
useEffect(()=>{
fetch(`http://서버주소/proverbs?q=${filter}`)
.then(resp=>resp.json())
.then(result =>{
setProverbs(result);
});
}, [filter]);
####AJAX 요청이 매우 느릴 경우?
: 로딩화면 구현은 필수적! -> 상태 처리 필요!
const [isLoading, setIsLoading] = useState(true);
// 생략
return {isLoading ? <LoadingIndicator> : <div>로딩 완료 화면</div>}
useEffect(()=>{
setIsLoading(true);
fetch(`http://서버주소/proverbs?q=${filter}`)
.then(resp=> resp.json())
.then(result =>{
setProverbs(result)
setIsLoading(false);
});
},[filter])
1) React에서 Ajax 요청을 보낼 때는 Effect Hook을 사용할 수 있다.
2) 함수 내에서 Ajax 요청을 할 때 외부 상태를 바꾸기 때문에 순수함수가 아니다!!
3)
A. sum 함수가 외부의 변수인 c를 사용하였습니다. 이 경우 인자로 받아오지 않은 변수 c가 변함에 따라 함수의 결괏값이 달라지므로 순수 함수가 아닙니다.
let c = 12;
function sum(a, b){
return a + b + c
}
4) Effect hook에 대한 설명으로 옳지 않은 것을 고르세요.
React 함수 내에서만 호출해야 한다.-> 맞음!!!
일반적으로 반복문, 조건문 내부에서도 사용한다. -> 틀림!!!
5) 상태 끌어올리기에 대한 설명으로 옳지 않은 것을 고르세요.
하위 컴포넌트에서 정의된 state를 상위 컴포넌트로 전달하는 것을 말한다.-> 틀림
6)map 함수의 key prop을 지정할 때에는 일반적으로 Math.random() 메서드를 사용한다.(틀림!!!!!!)