const [(state변수명), set(state변수명)] = useState(초기값);
setState(새 state값 or state 연산)
const [state, setState] = useState({});
setState((prev) => {
return {...prev, ...updatedValues};
});
위 내용에 관련된 예시
//..생략
const handleClick = () => {
setCount((count) => count + 1);
setIsClicked((clicked) => !clicked);
//setIsClicked까지 끝나야 리렌더링 함
}
출처: https://immigration9.github.io/react/2021/06/12/automatic-batching-react.html
function ex() {
const [state, setState] = useState(0);
useEffect(() => {
fetch(~~~어쩌구저쩌구 URL);
}, [state]);
//state가 업데이트 될 때만 useEffect가 실행된다.
useEffect(() => {
//...생략
}, []);
//dependency로 빈 배열을 넣을 경우, useEffect가 최초 렌더링 시 1회만 실행된다
//...생략
}
useEffect(() => {
//...생략
return () => {
//clean-up 부분
}
}, [state]);
const callbackFunc = () => {
console.log("be declared whenever it renders");
};
//이 함수는 렌더링 될 때마다 재선언되기 때문에 메모리 낭비가 일어남
const funcWrapped = useCallback(() => {
console.log("be declared only at the first rendering");
}, []);
//이 함수는 첫 렌더링 시에만 선언되고 더 이상 재선언되지 않음
const memoizedValue = useMemo(() => {
expensiveProcess(productNum)
}, [productNum]);
const ref변수명 = useRef(초기값);
//ref변수명 = { current: 초기값 }
//ref 변수명은 맘대로 정할 수 있음
참고: https://www.youtube.com/watch?v=VxqZrL4FLz8&ab_channel=%EB%B3%84%EC%BD%94%EB%94%A9
function Counter() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();
useEffect(() => {
prevCountRef.current = count;
});
const prevCount = prevCountRef.current;
return <h1>Now: {count}, before: {prevCount}</h1>;
}
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
function Counter() {
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);
return <h1>Now: {count}, before: {prevCount}</h1>;
}
예시)
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1);
// 이 effect는 'count' state에 따라 달라짐
}, 1000);
return () => clearInterval(id);
}, [count]);
// 이렇게 되면 매번 렌더링마다 setInterval의 타이머가
// 클린업 되었다가 재설정되기 때문에 setInterval이 아니라 setTimeout처럼 실행됨
return <h1>{count}</h1>;
}
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(c => c + 1);
// ✅ 이것은 외부의 'count' 변수에 의존하지 않고
// 이전 값을 참조하여 count를 업데이트 함
}, 1000);
return () => clearInterval(id);
}, []);
//setInterval 자체는 최초 렌더링 시 즉, 1번만 실행이 되지만
// 그 안에 있는 setCount는 1초마다 이전 값을 참조하여 count를 계속 업데이트 하게 된다
return <h1>{count}</h1>;
}
function Form() {
const [text, updateText] = useState('');
const textRef = useRef();
useEffect(() => {
textRef.current = text;
});
// ref에 input으로 입력한 값 저장
// ref 값은 렌더링마다 재선언되지 않고 그대로 유지되고, 렌더링 발생시키지 않음
const handleSubmit = useCallback(() => {
const currentText = textRef.current;
// ref값을 currentText 변수에 저장
alert(currentText);
}, [textRef]);
//handleSubmit 함수는 textRef가 변경될 때만 다시 선언된다
// handleSubmit 함수는 textRef 값을 제출했을 때만 실행됨
// textRef는 렌더링 될때에도 유지되기 때문에 useCallback이 자주 재선언되지 않아 메모리 낭비 줄이기 가능
return (
<>
<input value={text} onChange={e => updateText(e.target.value)} />
<ExpensiveTree onSubmit={handleSubmit} />
</>
);
}
useEffect(()=>{
fetch(get요청할 URL)
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setItems(result);
},
(error) => {
setIsloaded(true);
setError(error);
}
//에러 처리 시 try catch보다는 then으로 error다루는게 나음
)
}, [])
npm install axios
import axios from "axios";
function App () {
useEffect(() => {
axios.get(URL적기)
.then((result) => console.log(result.data))
//result.data에 axios로 가져온 데이터 들어있음
.catch((error) => console.log(error));
}, []);
}