useEffect(function, deps)
- function : 렌더링 이후 실행할 함수
- deps : 특정한 값이 변경될 때, effect함수를 실행하고 싶을 경우 배열안에 그 값을 넣어줌
A. useEffect(()=> {});
기본형태로 렌더링이 완료될 때마다 실행
B. useEffect(() => {}. []);
useEffect에 설정한 함수가, 화면에 가장 처음 렌더링 될 때만 실행하고 싶을 경우 사용
C. useEffect(() => {document.tile = number }. [number];
첫 렌더링 후 한번 실행, 그 후에는 [] 안의 값이 업데이트 될 때만 실행
D. useEffect(() => { return () => {} })
첫 렌더링 된 후 실행, 그 후에는 렌더링 완료후 뒷정리 함수 반환 후에 실행
React 컴포넌트가 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 side Effect라고 함
대표적 예로 어떤 데이터르르 가져오기 위해 외부 API를 호출하는 경우, 화면에 렌더링할 수 있는 것은 먼저 렌더링하고 실제 데이터는 비동기로 가져오는 것이 권장
import React, { useState, useEffect } from "react";
function UserListFunction() {
const [loading, setLoading] = useState(true);
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((users) => {
setUsers(users); //외부에서 받아온 데이터로 users값이 변하게됨 / side effect 발생
setLoading(false);
});
});
if (loading) return <div>Loading...</div>;
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
왜냐하면, 한 컴포넌트에서 hook을 여러번 호출할 경우, React는 hook 호출의 순서를 기억하고있다. hook 호출의 순서대로 각각의 hook 호출이 무엇인지 식별하는 것입니다.
그렇기 때문에 만약에 조건문 안에 hook이 있을 경우에, 그 조건문이 실행되지 못하면 순서가 뒤바뀌므로, React는 hook을 알맞게 대응할 수가 없습니다.
만약 조건부로 이펙트를 실행하고 싶다면, hook 안에 조건문을 넣어서 이를 해결할 수 있다
-일반적인 JavaScript 함수에서 hook을 호출하면 안된다.
전체 목록 데이터를 불러오고, 목록을 검색으로 filter하는 방법
import { useEffect, useState} from "react";
export default functino App() {
const [proverbs, setProverbs] = useState([]); // 빈배열
const [filter, setFilter] = useState('');
useEffect(() => {
const result = getProverbs(); // 속담이 담긴 배열
setProverbs(result); //속담이 담긴 배열을 받아와서 변수에 집어넣음
}, []) // 처음 한번만 렌더링
const handleChange = (e) => {
setFilter(e.target.value); // input에 입력하면 filter가 입력값으로 바뀜
}
return (
<div className="App">
<input type="text" value={filter} onChange={handleChange} />
<ul>
{proverbs // 받아온 배열에서, input에 입력한 값을 포함하는지 검사
.filter((prvb) => {
return prvb.toLowerCase().includes(filter.toLowerCase());
})
.map((prvb, i) => (
<Proverb saying={prvb} key={i} />
))}
</ul>
</div>
);
}
function Proverb({ saying }) { // 자식 컴포넌트로, 걸러진 배열을 props로 받음
return <li>{saying}</li>;
}
컴포넌트 외부로 API 요청을 할 떄, 필터링한 결과를 받아오는 방법
import { useEffect, useState } from "react";
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); // filter를 여기 집어넣음으로 filter가 바뀔때마다 넘어오는 배열이 달라짐
setProverbs(result); // 바뀐 배열
}, [filter]); // filter가 바뀔 때마다 렌더링, 즉 input에 변화가 있을때마다 렌더링 반복
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 }) { // 자식 컴포넌트 props를 받아옴
return <li>{saying}</li>;
}
getProverbs를 받아올 때, filter가 추가되어있음
export function getProverbs(filterBy = "") {
const json = localStorage.getItem("proverbs");
const proverbs = JSON.parse(json) || [];
return proverbs.filter((prvb) =>
prvb.toLowerCase().includes(filterBy.toLowerCase())
);
}