컴포넌트는 컴포넌트 바깥에서 props를 이용해 데이터를 전달받음
단방향 데이터 흐름(one-way data flow)
(맞으면 state 아님)
(맞으면 state 아님)
(맞으면 state 아님)
ex) 하위 컴포넌트의 클릭 이벤트가 부모의 상태를 바꾸어야만 하는 상황 => 새로운 트윗 추가
상위 컴포넌트의 "상태를 변경하는 함수" 그 자체를 하위 컴포넌트로 전달하고, 이 함수를 하위 컴포넌트가 실행한다
함수 내 어떤 구현이 함수 외부에 영향을 끼치는 경우
React에서는 컴포넌트 내에서 fetch를 사용해 API정보를 가져오거나 이벤트를 활용해 DOM을 직접 조작할 때 Side Effect가 발생했다고 함
let foo = 'hello';
function bar() {
foo = 'world';
}
bar(); // bar는 side effect를 발생시킴
오직 함수의 입력만이 함수의 결과에 영향을 주는 함수
순수 함수에는 side effect가 없다
어떤 전달 인자가 주어졌을 때 항상 똑같은 값이 리턴되는 것을 보장하기 때문에 예측 가능한 함수임
=> Math.random()이 순수함수가 될 수 없는 이유
function upper(str) {
return str.toUpperCase(); // toUpperCase는 원본을 수정하지 않는다 = immutable
}
upper('hello') // 'HELLO'
SetTimeout
)fetch API
, localStorage
)컴포넌트 내에서 Side Effect를 실행할 수 있게 하는 Hook
새롭게 컴포넌트가 렌더링 될 때 Effect Hook 이 실행됨
useState
와 useEffect
가 여러번 호출되는 과정에서도 Hook의 상태를 올바르게 유지할 수 있도록 해줌useEffect
의 두 번째 인자는 배열. 배열은 조건(어떤 값의 변경이 일어날 때)을 담고 있음.
useEffect(함수, [])
=> 빈배열 넣기 => 컴포넌트가 처음 생성될 때만 effect함수가 실행됨useEffect(함수)
=> 아무것도 넣지 않기 => 컴포넌트가 처음 생성되거나 props가 업데이트되거나 상태(state)가 업데이트 될 때import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";
export default function App() {
const [proverbs, setProverbs] = useState([]);
const [filter, setFilter] = useState("");
useEffect(() => {
console.log("언제 effect 함수가 불릴까요?");
const result = getProverbs();
setProverbs(result);
}, []);
const handleChange = (e) => {
setFilter(e.target.value);
};
return (
<div className="App">
필터
<input type="text" value={filter} onChange={handleChange} />
<ul>
{proverbs
.filter((prvb) => {
return prvb.toLowerCase().includes(filter.toLowerCase());
})
.map((prvb, i) => (
<Proverb saying={prvb} key={i} />
))}
</ul>
</div>
);
}
function Proverb({ saying }) {
return <li>{saying}</li>;
}
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>;
}
장점 | 단점 | |
---|---|---|
컴포넌트 내부처리 | HTTP 요청의 빈도 줄일 수 있음 | 브라우저(클라이언트)의 메모리 상에 많은 데이터를 갖게 되므로 클라이언트 부담이 늘어난다 |
컴포넌트 외부처리 | 클라이언트가 필터링 구현을 생각하지 않아도 된다 | 빈번한 HTTP 요청이 일어나고 서버가 필터링을 처리하기 때문에 서버에 부담이 간다 |
명언제공 API의 엔드포인트 : http://서버주소/proverbs
useEffect(() => {
fetch(`http://서버주소/proverbs?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
});
}, [filter]);