REACT HOOKS
hook μ λ°°μ°κΈ° μν΄μ npx create-react-app hooks-tuotrial μ ν΄μ£ΌμΈμ!
1. useState
useStateλ κ°μ₯ κΈ°λ³Έμ μΈ Hook μΌλ‘μ, ν¨μν μ»΄ν¬λνΈμμλ κ°λ³μ μΈ μνλ₯Ό μ§λκ³
μμ μ μκ² ν΄μ€λλ€. λ§μ½μ ν¨μν μ»΄ν¬λνΈμμ μνλ₯Ό κ΄λ¦¬ν΄μΌ λλ μΌμ΄ λ°μνλ€λ©΄
μ΄ Hook μ μ¬μ©νμλ©΄ λ©λλ€.
νλ² μ΄ κΈ°λ₯μ μ¬μ©ν΄μ μ«μ μΉ΄μ΄ν°λ₯Ό ꡬνν΄λ³΄κ² μ΅λλ€.
src λλ ν°λ¦¬μ Counter.js νμΌμ μμ±νκ³ λ€μ μ½λλ₯Ό μ λ ₯ν΄λ³΄μΈμ
Counter.js
import React, { useState } from 'react';
const Counter = () => {
const [value, setValue] = useState(0);
return (
<div>
<p>
νμ¬ μΉ΄μ΄ν° κ°μ <b>{value}</b> μ
λλ€.
</p>
<button onClick={() => setValue(value + 1)}>+1</button>
<button onClick={() => setValue(value - 1)}>-1</button>
</div>
);
};
export default Counter;
Counter μ»΄ν¬λνΈλ₯Ό λ λλ§
App.js
import React from 'react';
import './App.css';
import Counter from './Counter';
const App = () => {
return <Counter />;
};
export default App;
1.1 useState λ₯Ό μ¬λ¬λ² μ¬μ©νκΈ°
νλμ useState ν¨μλ νλμ μν κ°λ§ κ΄λ¦¬λ₯Ό ν μ μκΈ° λλ¬Έμ λ§μ½μ μ»΄ν¬λνΈμμ
κ΄λ¦¬ν΄μΌ ν μνκ° μ¬λ¬ κ°λΌλ©΄ useState λ₯Ό μ¬λ¬λ² μ¬μ©νλ©΄ λλ€.
src λλ ν°λ¦¬μ Info.js νμΌμ μμ±νκ³ λ€μμ μ½λλ₯Ό μμ±νμΈμ
Info.js
import React, { 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>
<div>
<input value={name} onChange={onChangeName} />
<input value={nickname} onChange={onChangeNickname} />
</div>
<div>
<div>
<b>μ΄λ¦: </b> {name}
</div>
<div>
<b>λλ€μ: </b>
{nickname}
</div>
</div>
</div>
);
};
export default Info;
App μ»΄ν¬λνΈμμ λ λλ§
App.js
import React from 'react';
import './App.css';
import Info from './Info';
const App = () => {
return <Info />;
};
export default App;
2. useEffect
리μ‘νΈ μ»΄ν¬λνΈκ° λ λλ§ λ λλ§λ€ νΉμ μμ μ μννλλ‘ μ€μ ν μ μλ
Hook μ λλ€. ν΄λμ€ν μ»΄ν¬λνΈμ componentDidMount μ componentDidUpdate λ₯Ό
ν©μΉ ννλ‘ λ³΄μλ 무방
Info μ»΄ν¬λνΈμ useEffect λ₯Ό μ μ©
Info.js
import React, { useState, useEffect } from 'react';
const Info = () => {
const [name, setName] = useState('');
const [nickname, setNickname] = useState('');
useEffect(() => {
console.log('λ λλ§μ΄ μλ£λμμ΅λλ€!');
console.log({
name,
nickname,
});
});
const onChangeName = e => {
setName(e.target.value);
};
const onChangeNickname = e => {
setNickname(e.target.value);
};
return (
<div>
<div>
<input value={name} onChange={onChangeName} />
<input value={nickname} onChange={onChangeNickname} />
</div>
<div>
<div>
<b>μ΄λ¦: </b> {name}
</div>
<div>
<b>λλ€μ: </b>
{nickname}
</div>
</div>
</div>
);
};
export default Info;
2.1 λ§μ΄νΈ λ λλ§ μ€ννκ³ μΆμ λ
λ§μ½ useEffect μμ μ€μ ν ν¨μκ° μ»΄ν¬λνΈκ° νλ©΄μ κ°μ₯ μ²μ λ λλ§ λ λλ§ μ€νλκ³
μ λ°μ΄νΈ ν κ²½μ°μλ μ€ν ν νμκ° μλ κ²½μ°μ ν¨μμ λλ²μ§Έ νλΌλ―Έν°λ‘ λΉμ΄μλ
λ°°μ΄μ λ£μ΄μ£Όμλ©΄ λ©λλ€.
Info.js - useEffect
useEffect(() => {
console.log('λ§μ΄νΈ λ λλ§ μ€νλ©λλ€.');
}, []);
2.2 νΉμ κ°μ΄ μ λ°μ΄νΈ λ λλ§ μ€ννκ³ μΆμ λ
useEffect λ₯Ό μ¬μ© ν λ νΉμ κ°μ΄ λ³κ²½μ΄ λ λλ§ νΈμΆνκ² νκ³ μΆμ κ²½μ°λ μμ
κ²μ λλ€.
Info.js - useEffect
useEffect(() => {
console.log(name);
}, [name]);
λ°°μ΄ μμλ useState λ₯Ό ν΅ν΄ κ΄λ¦¬νκ³ μλ μνλ₯Ό λ£μ΄μ€λ λκ³ , propsλ‘ μ λ¬λ°μ
κ°μ λ£μ΄μ£Όμ΄λ λ©λλ€.
2.3 λ·μ 리 ν¨μ
λ§μ½ μ»΄ν¬λνΈκ° μΈλ§μ΄νΈλκΈ° μ μ΄λ, μ λ°μ΄νΈ λκΈ° μ§μ μ μ΄λ ν μμ μ μννκ³
μΆλ€λ©΄ useEffect μμ λ·μ 리(cleanup) ν¨μλ₯Ό λ°νν΄μ£Όμ΄μΌ ν©λλ€.
Info.js - useEffect
useEffect(() => {
console.log('effect');
console.log(name);
return () => {
console.log('cleanup');
console.log(name);
};
});
App.js
import React, { useState } from 'react';
import './App.css';
import Info from './Info';
const App = () => {
const [visible, setVisible] = useState(false);
return (
<div>
<button
onClick={() => {
setVisible(!visible);
}}
>
{visible ? 'μ¨κΈ°κΈ°' : '보μ΄κΈ°'}
</button>
<hr />
{visible && <Info />}
</div>
);
};
export default App;
λ§μ½μ , μ€μ§ μΈλ§μ΄νΈ λ λλ§ λ·μ 리 ν¨μλ₯Ό νΈμΆνκ³ μΆμΌμλ€λ©΄ useEffect ν¨μμ
λλ²μ§Έ νλΌλ―Έν°μ λΉμ΄μλ λ°°μ΄μ λ£μΌμλ©΄ λ©λλ€.
Info.js - useEffect
useEffect(() => {
console.log('effect');
console.log(name);
return () => {
console.log('cleanup');
console.log(name);
};
});
3. useContext
μ΄ Hook μ μ¬μ©νλ©΄ ν¨μν μ»΄ν¬λνΈμμ Context λ₯Ό λ³΄λ€ λ μ½κ² μ¬μ© ν μ μμ΅λλ€
src λλ ν°λ¦¬μ ContextSample.js μ΄λΌλ μ»΄ν¬λνΈλ₯Ό λ§λ€μ΄λ³΄μΈμ
ContextSample.js
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('black');
const ContextSample = () => {
const theme = useContext(ThemeContext);
const style = {
width: '24px',
height: '24px',
background: theme,
};
return <div style={style} />;
};
export default ContextSample;
App.js
import React from 'react';
import ContextSample from './ContextSample';
const App = () => {
return <ContextSample />;
};
export default App;
4. useReducer
useReducer λ useState λ³΄λ€ μ»΄ν¬λνΈμμ λ λ€μν μν©μ λ°λΌ λ€μν μνλ₯Ό λ€λ₯Έ
κ°μΌλ‘ μ λ°μ΄νΈν΄μ£Όκ³ μΆμ μ¬μ©νλ Hook.
Reducerλ νμ¬ μνμ, μ λ°μ΄νΈλ₯Ό μν΄ νμν μ 보λ₯Ό λ΄μ μ‘μ (action) κ°μ μ λ¬ λ°μ
μλ‘μ΄ μνλ₯Ό λ°ννλ ν¨μμ λλ€. 리λμ ν¨μμμ μλ‘μ΄ μνλ₯Ό λ§λ€ λλ κΌ
λΆλ³μ±μ μ§μΌμ£Όμ΄μΌ ν©λλ€.
4.1 μΉ΄μ΄ν° ꡬννκΈ°
λ¨Όμ , κΈ°μ‘΄μ Counter μ»΄ν¬λνΈλ₯Ό useReducer λ₯Ό μ¬μ©νμ¬ λ€μ ꡬν
Counter.js
import React, { 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 μ 첫λ²μ§Έ νλΌλ―Έν°λ 리λμ ν¨μ, 그리λ λλ²μ§Έ νλΌλ―Έν°λ ν΄λΉ 리λμμ
κΈ°λ³Έ κ°μ λ£μ΄μ€λλ€. μ΄ Hookμ μ¬μ© νμ λμλ state κ°κ³Ό dispatch ν¨μλ₯Ό λ°μμ€κ²
λλλ°μ, μ¬κΈ°μ state λ νμ¬ κ°λ₯΄ν€κ³ μλ μνκ³ , dispatch λ μ‘μ μ λ°μμν€λ
ν¨μμ λλ€. dispatch(action) μ κ°μ ννλ‘, ν¨μ μμ νλΌλ―Έν°λ‘ μ‘μ κ°μ λ£μ΄μ£Όλ©΄
리λμ ν¨μκ° νΈμΆλλ ꡬ쑰μ λλ€.
useRedcuer μ μ¬μ©νμ λμ κ°μ₯ ν° μ₯μ μ μ»΄ν¬λνΈ μ λ°μ΄νΈ λ‘μ§μ μ»΄ν¬λνΈ λ°κΉ₯μΌλ‘
λΉΌλΌ μ μλ€λ μ μ λλ€.
App.js
import React from 'react';
import Counter from './Counter';
const App = () => {
return <Counter />;
};
export default App;
4.2 μΈν μν κ΄λ¦¬νκΈ°
μ΄λ²μλ useReducer λ₯Ό μ¬μ©νμ¬ Info μ»΄ν¬λνΈμμ μΈν μνλ₯Ό κ΄λ¦¬ν΄λ³΄κ² μ΅λλ€.
κΈ°μ‘΄μλ μΈνμ΄ μ¬λ¬ κ°μ¬μ useState λ₯Ό μ¬λ¬λ² μ¬μ©νλλ°μ, useReducer λ₯Ό μ¬μ©νλ€λ©΄
μ°λ¦¬κ° κΈ°μ‘΄μ ν΄λμ€ν μ»΄ν¬λνΈμμ input νκ·Έμ name κ°μ ν λΉνκ³ e.target.name μ
μ°Έμ‘°νμ¬ setState λ₯Ό ν΄μ€ κ²κ³Ό μ μ¬ν λ°©μμΌλ‘ μμ μ μ²λ¦¬ ν μ μμ΅λλ€.
Info.js
import React, { useReducer } from 'react';
function reducer(state, action) {
return {
...state,
[action.name]: action.value,
};
}
const Info = () => {
const [state, dispatch] = useReducer(reducer, {
name: '',
nickname: '',
});
const { name, nickname } = state;
const onChange = e => {
dispatch(e.target);
};
return (
<div>
<div>
<input name="name" value={name} onChange={onChange} />
<input name="nickname" value={nickname} onChange={onChange} />
</div>
<div>
<div>
<b>μ΄λ¦:</b> {name}
</div>
<div>
<b>λλ€μ: </b>
{nickname}
</div>
</div>
</div>
);
};
export default Info;
App.js
import React from 'react';
import Info from './Info';
const App = () => {
return <Info />;
};
export default App;
5. useMemo
useMemo λ₯Ό μ¬μ©νλ©΄ ν¨μν μ»΄ν¬λνΈ λ΄λΆμμ λ°μνλ μ°μ°μ μ΅μ ν ν μ μμ΅λλ€.
λ¨Όμ 리μ€νΈμ μ«μλ€μ μΆκ°νλ©΄ ν΄λΉ μ«μλ€μ νκ· μ λνλ΄λ ν¨μν μ»΄ν¬λνΈλ₯Ό
μμν΄ λ΄ μλ€.
src λλ ν°λ¦¬μ Averge.js νμΌμ μμ±νμΈμ
Average.js
import React, { useState } from 'react';
const getAverage = numbers => {
console.log('νκ· κ° κ³μ°μ€..');
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 = e => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
};
return (
<div>
<input value={number} onChange={onchange} />
<button onClick={onInsert}>λ±λ‘</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>νκ· κ°:</b> {getAverage(list)}
</div>
</div>
);
};
export default Average;
App.js
import React from 'react';
import Average from './Average';
const App = () => {
return <Average />;
};
export default App;
νκ· κ°μ μ 보μ¬μ§κ³ μλλ°, μ«μλ₯Ό λ±λ‘ν λλΏλ§ μλλΌ μΈν λ΄μ©μ΄ μμ λ λλ
μ°λ¦¬κ° λ§λ getAverage ν¨μκ° νΈμΆλκ³ μλκ²μ νμΈ ν μ μμ΅λλ€. μΈν λ΄μ©μ΄ λ°λ
λ νκ· κ°μ λ€μ κ³μ° ν νμκ° μλλ°, μ΄λ κ² λ λλ§ ν λλ§λ€ κ³μ°μ νλ κ²μ λλΉ.
useMemo Hook μ μ¬μ©νλ©΄ μ΄λ¬ν μμ μ μ΅μ ν ν μ μμ΅λλ€. λ λλ§ νλ κ³Όμ μμ
νΉμ κ°μ΄ λ°λμμ λλ§ μ°μ°μ μ€ννκ³ λ§μ½μ μνλ κ°μ΄ λ°λ κ²μ΄ μλλΌλ©΄ μ΄μ μ
μ°μ°νλ κ²°κ³Όλ₯Ό λ€μ μ¬μ©νλ λ°©μμ λλ€.
Average.js
import React, { useState, useMemo } from 'react';
const getAverage = numbers => {
console.log('νκ· κ° κ³μ°μ€..');
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 = e => {
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>
<div>
<b>νκ· κ°:</b> {avg}
</div>
</div>
);
};
export default Average;
list λ°°μ΄μ λ΄μ©μ΄ λ°λ λμλ§ getAverage ν¨μκ° νΈμΆ
6. useCallback
useCallback μ useMemo μ μλΉν λΉμ·ν ν¨μμ λλ€. μ£Όλ‘ λ λλ§ μ±λ₯μ μ΅μ νν΄μΌ
νλ μν©μμ μ¬μ©νλλ°μ, μ΄ Hook μ μ¬μ©νλ©΄ μ΄λ²€νΈ νΈλ€λ¬ ν¨μλ₯Ό νμν λλ§ μμ±
ν μ μμ΅λλ€.
μ°λ¦¬κ° λ°©κΈ κ΅¬νν Average μ»΄ν¬λνΈλ₯Ό 보면, onChange μ onInsert λΌλ ν¨μλ₯Ό
μ μΈν΄μ£Όμμ΅λλ€. μ΄λ κ² μ μΈμ νκ² λλ©΄ μ»΄ν¬λνΈκ° 리λ λλ§ λ λλ§λ€ μ΄ ν¨μλ€μ΄
μλ‘ μμ±λ©λλ€. λλΆλΆμ κ²½μ°μλ μ΄λ¬ν λ°©μμ΄ λ¬Έμ κ° λμ§ μμ§λ§, μ»΄ν¬λνΈμ
λ λλ§μ΄ μμ£Ό λ°μνκ±°λ, λ λλ§ ν΄μΌ ν μ»΄ν¬λνΈμ κ°μκ° λ§μμ§λ€λ©΄ μ΄ λΆλΆμ
μ΅μ ν ν΄μ£Όμλ κ²μ΄ μ’μ΅λλ€.
Average.js
import React, { useState, useMemo, useCallback } from 'react';
const getAverage = numbers => {
console.log('νκ· κ° κ³μ°μ€..');
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(
e => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
},
[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>
<div>
<b>νκ· κ°:</b> {avg}
</div>
</div>
);
};
export default Average;
useCallback μ 첫λ²μ§Έ νλΌλ―Έν°μλ μ°λ¦¬κ° μμ±ν΄μ£Όκ³ μΆμ ν¨μλ₯Ό λ£μ΄μ£Όκ³ , λλ²μ§Έ
νλΌλ―Έν°μλ λ°°μ΄μ λ£μ΄μ£Όλ©΄ λλλ° μ΄ λ°°μ΄μλ μ΄λ€ κ°μ΄ λ°λμμ λ ν¨μλ₯Ό μλ‘
μμ±ν΄μ£Όμ΄μΌ νλμ§ λͺ μν΄μ£Όμ΄μΌ ν©λλ€.
λ§μ½μ onChange μ²λΌ λΉμ΄μλ λ°°μ΄μ λ£κ² λλ©΄ μ»΄ν¬λνΈκ° λ λλ§ λ λ λ¨ νλ²λ§
ν¨μκ° μμ±λλ©°, onInsert μ²λΌ λ°°μ΄ μμ number μ list λ₯Ό λ£κ² λλ©΄ μΈν λ΄μ©μ΄
λ°λκ±°λ μλ‘μ΄ νλͺ©μ΄ μΆκ° λ λλ§λ€ ν¨μκ° μμ±λ©λλ€.
7. useRef
useRef Hook μ ν¨μν μ»΄ν¬λνΈμμ ref λ₯Ό μ½κ² μ¬μ© ν μ μκ² ν΄μ€λλ€. Average
μ»΄ν¬λνΈμμ λ±λ‘ λ²νΌμ λλ μ λ ν¬μ»€μ€κ° μΈν μͺ½μΌλ‘ λμ΄κ°λλ‘ μ½λλ₯Ό
μμ±ν΄λ³΄κ² μ΅λλ€.
import React, { useState, useMemo, useRef, useCallback } from 'react';
const getAverage = numbers => {
console.log('νκ· κ° κ³μ°μ€..');
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(
e => {
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>
<div>
<b>νκ· κ°:</b> {avg}
</div>
</div>
);
};
export default Average;
7.1 λ‘컬 λ³μ μ¬μ©νκΈ°
μΆκ°μ μΌλ‘, μ»΄ν¬λνΈ λ‘컬 λ³μλ₯Ό μ¬μ©ν΄μΌ ν λλ useRef λ₯Ό νμ© ν μ μμ΅λλ€. μ¬κΈ°μ
λ‘컬 λ³μλΌ ν¨μ, λ λλ§μ΄λμ κ΄κ³ μμ΄ λ°λ μ μλ κ°μ μλ―Έν©λλ€. λ§μ½μ ν΄λμ€
ννμ μ»΄ν¬λνΈλ‘ λ°μ§μλ©΄ λ€μκ³Ό κ°μ μ½λμ λλ€.
import React, { Component } from 'react';
class MyComponent extends Component {
id = 1
setId = (n) => {
this.id = n;
}
printId = () => {
console.log(this.id);
}
render() {
return (
<div>
MyComponent
</div>
);
}
}
export default MyComponent;
μ΄λ¬ν μ½λλ₯Ό ν¨μν μ»΄ν¬λνΈλ‘ μμ±νλ€λ©΄ λ€μκ³Ό κ°μ΄ ν μ μμ΅λλ€.
import React, { useRef } from 'react';
const RefSample = () => {
const id = useRef(1);
const setId = (n) => {
id.current = n;
}
const printId = () => {
console.log(id.current);
}
return (
<div>
refsample
</div>
);
};
export default RefSample;
8. 컀μ€ν Hooks λ§λ€κΈ°
λ§μ½μ μ¬λ¬ μ»΄ν¬λνΈμμ λΉμ·ν κΈ°λ₯μ 곡μ νκ² λλ μΌμ΄ λ°μνλ€λ©΄ μ΄λ₯Ό μ°λ¦¬λ€λ§μ
Hook μ μμ±νμ¬ λ‘μ§μ μ¬μ¬μ© ν μ μμ΅λλ€.
8.1 useInputs
νλ² μ°λ¦¬κ° κΈ°μ‘΄μ Info μ»΄ν¬λνΈμμ μ¬λ¬κ°μ μΈνμ κ΄λ¦¬νκΈ° μνμ¬ useReducer λ‘
ν΄κ²°νλ μμ±νλ λ‘μ§μ useInputs λΌλ HookμΌλ‘ λ°λ‘ λΆλ¦¬ν΄λ³΄κ² μ΅λλ€
src λλ ν°λ¦¬μ useInputs.js νμΌμ λ§λ€κ³ λ€μ μ½λλ₯Ό μμ±ν΄λ³΄μΈμ
useInputsjs
import { useReducer } from 'react';
function reducer(state, action) {
return {
...state,
[action.name]: action.value,
};
}
export default function useInputs(initialForm) {
const [state, dispatch] = useReducer(reducer, initialForm);
const onChange = e => {
dispatch(e.target);
};
return [state, onChange];
}
Info.js
import React from 'react';
import useInputs from './useInputs';
const Info = () => {
const [state, onChange] = useInputs({
name: '',
nickname: '',
});
const { name, nickname } = state;
return (
<div>
<div>
<input name="name" value={name} onChange={onChange} />
<input name="nickname" value={nickname} onChange={onChange} />
</div>
<div>
<div>
<b>μ΄λ¦:</b> {name}
</div>
<div>
<b>λλ€μ: </b>
{nickname}
</div>
</div>
</div>
);
};
export default Info;
8.2 usePromise
μ΄λ²μλ ν¨μν μ»΄ν¬λνΈμμ Promise λ₯Ό λ μ½κ² μ¬μ© ν μ μλ Hook μ λ§λ€μ΄λ΄ μλ€.
src λλ ν°λ¦¬μ usePromise.js νμΌμ μμ±νκ³ λ€μ μ½λλ₯Ό μ λ ₯ν΄λ³΄μΈμ
usePromise.js
import { useState, useEffect } from 'react';
export default function usePromise(promiseCreator, deps) {
const [resolved, setResolved] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const process = async () => {
setLoading(true);
try {
const result = await promiseCreator();
setResolved(result);
} catch (e) {
setError(e);
}
setLoading(false);
};
useEffect(() => {
process();
}, deps);
return [loading, resolved, error];
}
μ 컀μ€ν ν μμλ useStateμ useEffect λ₯Ό ν¨κ» μ¬μ©νμμ΅λλ€. μ΄ ν¨μλ νλ‘λ―Έμ€λ₯Ό
μμ±νλ promiseCreator μ, μΈμ νλ‘λ―Έμ€λ₯Ό μλ‘ λ§λ€μ§μ λν 쑰건μ μν deps
λ°°μ΄μ νλΌλ―Έν°λ‘ λ°μμ΅λλ€. μ΄ deps λ°°μ΄μ useEffect μ λλ²μ§Έ νλΌλ―Έν°λ‘ μ λ¬λλ©°,
κΈ°λ³Έκ°μ λΉμ΄μλ λ°°μ΄μ λλ€.
UsePromiseSample.js
import React from 'react';
import usePromise from './usePromise';
const wait = () => {
// 3μ΄ νμ λλλ νλ‘λ―Έμ€λ₯Ό λ°ν
return new Promise(resolve =>
setTimeout(() => resolve('Hello hooks!'), 3000)
);
};
const UsePromiseSample = () => {
const [loading, resolved, error] = usePromise(wait, []);
if (loading) return <div>λ‘λ©μ€..!</div>;
if (error) return <div>μλ¬ λ°μ!</div>;
if (!resolved) return null;
return <div>{resolved}</div>;
};
export default UsePromiseSample;
App.js
import React from 'react';
import UsePromiseSample from './UsePromiseSample';
const App = () => {
return <UsePromiseSample />;
};
export default App;
velog.io/@velopert/react-hooks
리μ‘νΈμ Hooks μλ²½ μ 볡νκΈ°
React Hooks λ v16.8 μ λμ λ κ°λ μΌλ‘μ, ν¨μν μ»΄ν¬λνΈμμλ μν κ΄λ¦¬λ₯Ό ν μ μλ useState, κ·Έλ¦¬κ³ λ λλ§ μ§ν μμ μ μ€μ νλ useEffect λ±μ κΈ°λ₯μ μ 곡ν©λλ€. μ΄μ λνμ¬ νλ² μμΈν
velog.io