π‘ useState
// useState ν¨μ μ¬μ©νκΈ°
import { useState } from "react";
const Counter = () => {
const [value, setValue] = useState(0);
return (
<div>
<p>νμ¬ μΉ΄μ΄ν° κ°μ {value} μ΄λ€.</p>
<button onClick={() => setValue(value + 1)}>+1</button>
<button onClick={() => setValue(value - 1)}>-1</button>
</div>
);
};
export default Counter;
- useState λ νλμ μν κ°λ§ κ΄λ¦¬ν μ μμΌλ μ»΄ν¬λνΈμμ κ΄λ¦¬ν΄μΌ ν μνκ° μ¬λ¬ κ°λΌλ©΄ useState λ₯Ό μ¬λ¬ λ² μ¬μ©νλ©΄ λλ€.
- useState(0) μ΄λ μ΄κΈ°κ°μ 0 μΌλ‘ νκ² λ€λ μλ―Έμ΄λ€.
- const [value, setValue] μμ 첫 λ²μ§Έ μμμΈ value λ μν κ°, λ λ²μ§Έ μμμΈ setValue λ μνλ₯Ό μ€μ νλ ν¨μμ΄λ€.
- μ΄ ν¨μμ νλΌλ―Έν°λ₯Ό λ£μ΄μ νΈμΆνλ©΄(setValue(value+1) κ³Ό κ°μ΄) μ λ¬λ°μ νλΌλ―Έν°λ‘ κ°μ΄ λ°λκ³ μ»΄ν¬λνΈκ° μ μμ μΌλ‘ 리λ λλ§νλ€.
μΉ μ€ν νλ©΄

useState μ¬λ¬ λ² μ¬μ©νκΈ°
import { useState } from "react";
const Info = () => {
const [name, setName] = useState("");
const [nickname, setNickname] = useState("");
const onChangeName = (e) => {
setName(e.target.value);
};
const onChangeNickName = (e) => {
setNickname(e.target.value);
};
return (
<div>
<input value={name} onChange={onChangeName} />
<input value={nickname} onChange={onChangeNickName} />
<div>μ΄λ¦ : {name}</div>
<div>λλ€μ : {nickname}</div>
</div>
);
};
export default Info;
μΉ μ€ν νλ©΄

π‘ useEffect
리μ‘νΈ μ»΄ν¬λνΈκ° λ λλ§ λ λλ§λ€ νΉμ μμ μ μννλλ‘ μ€μ ν μ μλ Hook μ΄λ€. useEffect λ κΈ°λ³Έμ μΌλ‘ λ λλ§λκ³ λ μ§νλ§λ€ μ€νλλ©°, λ λ²μ§Έ νλΌλ―Έν° λ°°μ΄μ 무μμ λ£λμ§μ λ°λΌ μ€νλλ μ‘°κ±΄μ΄ λ¬λΌμ§λ€. ν΄λμ€ ν μ»΄ν¬λνΈμΈ componentDidMount μ componentDidUpdate λ₯Ό ν©μΉ ννλ‘ λ³΄μλ 무방νλ€.
import { useState, useEffect } from "react";
const Info = () => {
const [name, setName] = useState("");
const [nickname, setNickname] = useState("");
useEffect(() => {
console.log("λ λλ§μ΄ μλ£λμμ΅λλ€.");
console.log({
nickname,
});
}, [nickname]);
const onChangeName = (e) => {
setName(e.target.value);
};
const onChangeNickName = (e) => {
setNickname(e.target.value);
};
return (
<div>
<input value={name} onChange={onChangeName} />
<input value={nickname} onChange={onChangeNickName} />
<div>μ΄λ¦ : {name}</div>
<div>λλ€μ : {nickname}</div>
</div>
);
};
export default Info;
useEffect λ₯Ό νΉμ κ°μ΄ μ λ°μ΄νΈ λ λλ§ νΈμΆνκ³ μΆμΌλ©΄, useEffect μ λ λ²μ§Έ νλΌλ―Έν°λ‘ μ λ¬λλ λ°°μ΄ [ ] μμ κ²μ¬νκ³ μΆμ κ°μ λ£μ΄ μ£Όλ©΄ λλ€.
useEffect(() => {
console.log("λ λλ§μ΄ μλ£λμμ΅λλ€.");
console.log({
nickname,
});
}, [nickname]);
κ²μ¬νκ³ μ νλ κ°μ nickname μΌλ‘ μ€μ νλλ nickname μ΄ λ°λ λλ§ useEffect μ ν¨μλ₯Ό μ€ννλ κ²μΌλ‘ λ°λμλ€.
μΉ μ€ν νλ©΄

useEffect λ·μ 리 νκΈ°
μ»΄ν¬λνΈκ° μΈλ§μ΄νΈλκΈ° μ μ΄λ μ λ°μ΄νΈ λκΈ° μ§μ μ μ΄λ ν μμ μ μννκ³ μΆμΌλ©΄ useEffect μμ λ·μ 리(clean up) ν¨μλ₯Ό λ°νν΄μ£Όμ΄μΌ νλ€.
// App.js
import React, { useState } from "react";
import Info from "./Info";
const App = () => {
const [visible, setVisible] = useState(false);
return (
<div>
<button
onClick={() => {
setVisible(!visible);
console.log(!visible);
}}
>
{visible ? "μ¨κΈ°κΈ°" : "보μ΄κΈ°"}
</button>
<hr />
{visible && <Info />}
</div>
);
};
export default App;
// Info.js
import { useState, useEffect } from "react";
const Info = () => {
const [name, setName] = useState("");
const [nickname, setNickname] = useState("");
useEffect(() => {
console.log("effect");
return () => { // cleanup ν¨μ λ°ν
console.log("unmount");
};
}, []);
const onChangeName = (e) => {
setName(e.target.value);
};
const onChangeNickName = (e) => {
setNickname(e.target.value);
};
return (
<div>
<input value={name} onChange={onChangeName} />
<input value={nickname} onChange={onChangeNickName} />
<div>μ΄λ¦ : {name}</div>
<div>λλ€μ : {nickname}</div>
</div>
);
};
export default Info;
λ λλ§ λ λλ§λ€ λ·μ 리 ν¨μκ° κ³μ λνλλ κ²μ νμΈν μ μλ€. λ·μ 리 ν¨μκ° νΈμΆλ λλ μ λ°μ΄νΈ λκΈ° μ§μ μ κ°μ 보μ¬μ€λ€. μΈλ§μ΄νΈ(μ»΄ν¬λνΈκ° DOM μμ μ κ±°λλ κ², μ¬κΈ°μλ μ¨κΈ°κΈ° λ²νΌ λλ₯Ό λλ₯Ό μλ―Ένλ€.) λ λλ§ λ·μ 리 ν¨μλ₯Ό νΈμΆνκ³ μΆμΌλ©΄ useEffect ν¨μμ λ λ²μ§Έ νλΌλ―Έν°μ λΉμ΄ μλ λ°°μ΄μ λ£μΌλ©΄ λλ€.
μΉ μ€ν νλ©΄

π‘ useReducer
useReducer λ useState λ³΄λ€ λ λ€μν μ»΄ν¬λνΈ μν©μ λ°λΌ λ€μν μνλ₯Ό λ€λ₯Έ κ°μΌλ‘ μ λ°μ΄νΈ ν΄μ£Όκ³ μΆμ λ μ¬μ©νλ Hook μ΄λ€. Reducer λ νμ¬ μν(state), κ·Έλ¦¬κ³ μ λ°μ΄νΈλ₯Ό μν΄ νμν μ 보λ₯Ό λ΄μ action κ°μ μ λ¬λ°μ μλ‘μ΄ μνλ₯Ό λ°ννλ ν¨μμ΄λ€. useReducer μμ action μ κ·Έ μ΄λ€ κ°λ μ¬μ© κ°λ₯νλ©°, reducer ν¨μμμ μλ‘μ΄ μνλ₯Ό λ§λ€ λλ λ°λμ λΆλ³μ±μ μ§μΌ μ£Όμ΄μΌ νλ€.
// useReducer μ¬μ©νκΈ°
import { useReducer } from "react";
function reducer(state, action) {
switch (action.type) {
case "INCREMENT":
return { value: state.value + 1 };
case "DECREMENT":
return { value: state.value - 1 };
default:
return state;
}
}
const Counter = () => {
const [state, dispatch] = useReducer(reducer, { value: 0 });
return (
<div>
<p>
νμ¬ μΉ΄μ΄ν° κ°μ <b>{state.value}</b>μ
λλ€.
</p>
<button onClick={() => dispatch({ type: "INCREMENT" })}>+1</button>
<button onClick={() => dispatch({ type: "DECREMENT" })}>-1</button>
</div>
);
};
export default Counter;
useReducer μ 첫 λ²μ§Έ νλΌλ―Έν°μλ reducer ν¨μλ₯Ό λ£κ³ , λ λ²μ§Έ νλΌλ―Έν°μλ ν΄λΉ reducer μ κΈ°λ³Έκ° {value: 0} μ λ£μ΄μ€λ€. μ΄ Hook μ μ¬μ©νλ©΄ state κ°κ³Ό dispatch ν¨μλ₯Ό λ°μ μ¨λ€. μ¬κΈ°μ state λ νμ¬ κ°λ¦¬ν€κ³ μλ μνκ³ , dispatch λ μ‘μ μ λ°μμν€λ ν¨μμ΄λ€. dispatch(action) κ³Ό κ°μ ννλ‘, ν¨μ μμ νλΌλ―Έν°λ‘ action κ°μ λ£μ΄μ£Όλ©΄ reducer ν¨μκ° νΈμΆλλ ꡬ쑰μ΄λ€.
// Info.js
import { useReducer } from "react";
function reducer(state, action) {
return {
...state, // useReducer λ‘λΆν° μ λ¬λ°μ state κ° (name:'', nickname:'') 볡μ¬
[action.name]: action.value, // action.name μ e.target.name (input μ name) μ΄λ©° action.value λ e.target.value (input μ value) μΈ κ²μ΄λ€.
};
}
const Info = () => {
const [state, dispatch] = useReducer(reducer, {
name: "", // reducer μ ...state κ°μΌλ‘ μ λ¬νκΈ°
nickname: "",
});
const { name, nickname } = state; // state κ° κ°μ§κ³ μλ name, nickname κ°μ name, nickname νλμ λ£μ΄μ€λ€.
const onChange = (e) => {
dispatch(e.target); // action μ e.target
console.log(e.target);
};
return (
<div>
<input name="name" value={name} onChange={onChange} />
<input name="nickname" value={nickname} onChange={onChange} />
<div>μ΄λ¦ : {name}</div>
<div>λλ€μ : {nickname}</div>
</div>
);
};
export default Info;
dispatch(e.target) μΌλ‘ μ¬κΈ°μ dispatch κ° μ λ¬νλ action μ e.target μ΄λ€. μ¦, action.name μ e.target.name μ΄κ³ μ΄κ²μ input μμμ name μμ±μ λ§νλ€. action.value λ e.target.value μ΄κ³ μ΄κ²μ input μμμ value μμ±μ λ§νλ€. λ°λΌμ μμ input μμμ name="name" λ° name="nickname" μ λͺ μν΄μ£Όμ§ μμΌλ©΄ input μ κ° μ λ ₯μ΄ λΆκ°νκ³ , μ€νμ΄ μ λλ‘ λμ§ μλλ€.
μΉ μ€ν νλ©΄

π‘ useMemo
useMemo λ₯Ό μ¬μ©νλ©΄ ν¨μ μ»΄ν¬λνΈ λ΄λΆμμ λ°μνλ μ°μ°μ μ΅μ νν μ μλ€.
// Average.js
import { useState, useMemo } from "react";
const getAverage = (numbers) => {
console.log("νκ· κ° κ³μ° μ€..");
console.log(numbers);
if (numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState("");
const onChange = (e) => {
setNumber(e.target.value);
};
const onInsert = () => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber("");
};
// νΉμ κ°μ΄ λ°λμμ λλ§ μ°μ°μ μ€ννκ³ μνλ κ°μ΄ λ°λμ§ μμλ€λ©΄ μ΄μ μ μ°μ°νλ κ²°κ³Όλ₯Ό λ€μ μ¬μ©νλ λ°©μ
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input value={number} onChange={onChange} />
<button onClick={onInsert}>λ±λ‘</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
{/* list λ value λ§ λ΄κΈ΄ 리μ€νΈλ‘ λ¨. */}
<div>
<b>νκ· κ°: </b> {avg}
</div>
</div>
);
};
export default Average;
const avg = useMemo(() => getAverage(list), [list]);
useMemo λ₯Ό μ¬μ©νλ©΄ λ λλ§ νλ κ³Όμ μμ νΉμ κ°μ΄ λ°λμμ λλ§ μ°μ°μ μ€ννκ³ μνλ κ°μ΄ λ°λμ§ μμλ€λ©΄ μ΄μ μ μ°μ°νλ κ²°κ³Όλ₯Ό λ€μ μ¬μ©νλ λ°©μμ΄λ€. μμ μ½λμμλ list μ κ°μ΄ λ°λμμ λλ§ μ°μ°μ μ€ννλλ‘ λ λ²μ§Έ νλΌλ―Έν°λ₯Ό list λ‘ λμ΄ λ λλ§ ν λλ§λ€ κ²μ¬νλλ‘ νλ€.
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
list.map μΌλ‘ μΈν΄ value μ index μ λ°λΌ <li> νκ·Έλ‘ λ¬Άμ¬μ§κ³ list λ‘ λ¬Άμ¬μ Έ λμ¨λ€.
π‘ useCallback
// useCallback
import { useState, useMemo, useCallback } from "react";
const getAverage = (numbers) => {
console.log("νκ· κ° κ³μ° μ€..");
console.log(numbers);
if (numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState("");
const onChange = useCallback((e) => {
setNumber(e.target.value);
}, []); // μ»΄ν¬λνΈκ° μ²μ λ λλ§λ λλ§ ν¨μ μμ±
const onInsert = useCallback(() => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber("");
}, [number, list]); // number νΉμ list κ° λ°λμμ λλ§ ν¨μ μμ±
// νΉμ κ°μ΄ λ°λμμ λλ§ μ°μ°μ μ€ννκ³ μνλ κ°μ΄ λ°λμ§ μμλ€λ©΄ μ΄μ μ μ°μ°νλ κ²°κ³Όλ₯Ό λ€μ μ¬μ©νλ λ°©μ
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input value={number} onChange={onChange} />
<button onClick={onInsert}>λ±λ‘</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
{/* list λ value λ§ λ΄κΈ΄ 리μ€νΈλ‘ λ¨. */}
<div>
<b>νκ· κ°: </b> {avg}
</div>
</div>
);
};
export default Average;
useCallback μ 첫 λ²μ§Έ νλΌλ―Έν°μλ μμ±νκ³ μΆμ ν¨μλ₯Ό λ£κ³ , λ λ²μ§Έ νλΌλ―Έν°μλ λ°°μ΄μ λ£μΌλ©΄ λλ€. μ΄ λ°°μ΄μλ μ΄λ€ κ°μ΄ λ°λμμ λ ν¨μλ₯Ό μλ‘ μμ±ν΄μΌ νλμ§ λͺ μν΄μΌ νλ€. onChange μ²λΌ λΉμ΄ μλ λ°°μ΄μ λ£κ² λλ©΄ μ»΄ν¬λνΈκ° λ λλ§ λ λ λ§λ€μλ ν¨μλ₯Ό κ³μν΄μ μ¬μ¬μ©νκ² λλ©° onInsert μ²λΌ λ°°μ΄ μμ number μ list λ₯Ό λ£κ² λλ©΄ input λ΄μ©μ΄ λ°λκ±°λ μλ‘μ΄ νλͺ©μ΄ μΆκ°λ λ μλ‘ λ§λ€μ΄μ§ ν¨μλ₯Ό μ¬μ©νκ² λλ€.
π‘ useRef
ν¨μ μ»΄ν¬λνΈμμ ref λ₯Ό μ½κ² μ¬μ©ν μ μλλ‘ ν΄ μ€λ€.
// useRef
import { useState, useMemo, useCallback, useRef } from "react";
const getAverage = (numbers) => {
console.log("νκ· κ° κ³μ° μ€..");
console.log(numbers);
if (numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState("");
const inputEl = useRef(null);
const onChange = useCallback((e) => {
setNumber(e.target.value);
}, []); // μ»΄ν¬λνΈκ° μ²μ λ λλ§λ λλ§ ν¨μ μμ±
const onInsert = useCallback(() => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber("");
inputEl.current.focus();
}, [number, list]); // number νΉμ list κ° λ°λμμ λλ§ ν¨μ μμ±
// νΉμ κ°μ΄ λ°λμμ λλ§ μ°μ°μ μ€ννκ³ μνλ κ°μ΄ λ°λμ§ μμλ€λ©΄ μ΄μ μ μ°μ°νλ κ²°κ³Όλ₯Ό λ€μ μ¬μ©νλ λ°©μ
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input value={number} onChange={onChange} ref={inputEl} />
<button onClick={onInsert}>λ±λ‘</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
{/* list λ value λ§ λ΄κΈ΄ 리μ€νΈλ‘ λ¨. */}
<div>
<b>νκ· κ°: </b> {avg}
</div>
</div>
);
};
export default Average;
inputEl μ input μμλ₯Ό λ§νλ€. inputEl.current κ°μ΄ μ€μ input μμλ₯Ό κ°λ¦¬ν¨λ€. λ‘컬 λ³μλ λ λλ§κ³Ό μκ΄μμ΄ λ°λ μ μλ κ°μ μλ―Ένλ€.
λμ [리μ‘νΈλ₯Ό λ€λ£¨λ κΈ°μ ] μ μ°Έκ³ νμ¬ μμ±ν κΈμ λλ€.
'JavaScript > React' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[React] SPA λ? (0) | 2021.11.08 |
---|---|
[React] ν¨μ μ»΄ν¬λνΈμμ 리λ λλ§ μ΅μ νλ₯Ό μν λ°©λ² (0) | 2021.10.27 |
[React] μ»΄ν¬λνΈ μμ보기 (0) | 2021.10.26 |
[React] κΈμ°κΈ° κΈ°λ₯ ꡬννκΈ° (0) | 2021.10.22 |
[React] Redux ν΄λ ꡬ쑰 μ 리νκΈ° (0) | 2021.10.21 |
λκΈ