1. ํ (HOOK)
๐บ ๋ฆฌ์กํธ์๋ hook ํ ์ด๋ผ๋ ๊ฐ๋ ์ด ์๋ค.
๐ Hook ์ด๋?
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ ํด๋์คํ ์ปดํฌ๋ํธ(Class component)์ ํจ์ํ ์ปดํฌ๋ํธ(Functional component)๋ก ๋๋ฉ๋๋ค.
- ๋ฆฌ์กํธ ํ ์ ์๋ก์ด ๊ธฐ๋ฅ์ผ๋ก React 16.8๋ฒ์ ์ ์๋ก ์ถ๊ฐ๋ ๊ธฐ๋ฅ
- ํจ์ํํ์ ์ปดํฌ๋ํธ์์ ์ฌ์ฉ๋๋ ๋ช๊ฐ์ง ๊ธฐ์ ์ Hook์ด๋ผ๊ณ ๋ถ๋ฆ ๋๋ค. (useState, useEffect ๋ฑ)
- ๋ฆฌ์กํธ ํ ์ ํจ์ํ ์ปดํฌ๋ํธ๊ฐ ํด๋์คํ ์ปดํฌ๋ํธ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋๋ก ํด์ฃผ๋ ๊ธฐ๋ฅ์ด๋ค.
๐บ ํ ์๋ ๊ท์น์ด ์๋ค !
๐ Hook ๊ท์น
- ์ต์์ ์์๋ง Hook์ ํธ์ถํด์ผ ํ๋ค
- ๋ฐ๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ, ์ค์ฒฉ๋ ํจ์ ๋ด์์ Hook์ ์คํํ๋ฉด ์๋๋ค.
- ์ด ๊ท์น์ ๋ฐ๋ฅด๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋๋ง๋ค ํญ์ ๋์ผํ ์์๋ก Hook์ด ํธ์ถ๋๋ ๊ฒ์ด ๋ณด์ฅ๋๋ค.
- ๋ฆฌ์กํธ ํจ์ ์ปดํฌ๋ํธ์์๋ง Hook์ ํธ์ถํด์ผ ํ๋ค.
๐บ ์ด์ ํ (hook) ์ด ์ด๋ป๊ฒ ์๊ฒผ๋์ง ๋ด๋ณด์ !
๊ธฐ๋ณธ ํ ๋ค์ ๊ผญ ์์๋๋๋ก ํ์ !
๐ ํ (hook) ์ข ๋ฅ
1. useState(์ด๊ธฐ๊ฐ)
useState() : ๋ฐฐ์ด๋ฐํ ์ฒซ๋ฒ์งธ ๋ฐฐ์ด์ ์์์๋ ํ์ฌ๊ฐ์, ๋๋ฒ์งธ ์์๋ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ (setter) ๋ฅผ ๋ฐํํฉ๋๋ค.
const [data, setData] = useState('์ด๊ธฐ๊ฐ')
2. userEffect(์คํ์ํฌ ์ฝ๋ฐฑํจ์, ๊ฐ์ ๋ฐ๋ฅธ ๋ ๋๋ง ์ง์ -๋ฐฐ์ด)
ํจ์ํ ์ปดํฌ๋ํธ์์ ์ฌ์ด๋ ์ดํํธ(side effects)๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ํ ์ ๋๋ค.
์ฌ์ด๋ ์ดํํธ๋ ์ปดํฌ๋ํธ์ ๋ ๋๋ง ๊ณผ์ ์ธ๋ถ์์ ๋ฐ์ํ๋ ์์
3. useRef(์ด๊ธฐ๊ฐ)
ํน์ ํ๊ทธ์ ์ด๋ฆ๋ฌ๊ธฐ
4. useReducer(๋ฆฌ๋์ํจ์๋ช , state๊ฐ)
์ธ๋ถ์์ state์ฌ์ฉํ๊ธฐ
๋ฑ๋ฑ....
์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ์ต์ ํ ํ ....
- useMemo
- useCallback
2. ๋ผ์ดํ ์ฌ์ดํด (ํด๋์คํ ์ปดํฌ๋ํธ ๊ธฐ์ค) - userEffect
๐บ ๋ผ์ดํ ์ฌ์ดํด์ด ๋ญ๊น??
๋ง ๊ทธ๋๋ก ์๋ช ์ฃผ๊ธฐ๋ก ์ปดํฌ๋ํธ๊ฐ ์์ฑ, ์ ๋ฐ์ดํธ, ์ ๊ฑฐ ๋๋ ๊ณผ์ ์์
ํน์ ๋ฉ์๋๋ค์ด ํธ์ถ๋๋ ์์ ์ ๋งํ๋ค.
์ ! ์๋ช ์ฃผ๊ธฐ๋ฅผ ๋ค๋ฃจ๋ ํจ์๋ค์ ์์๋ณด์.
๐บ ๋ ๋๋ง ์ดํ์ ์คํ์ํฌ ์์ ์ด ์์ผ๋ฉด ์๋ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. (ํด๋์คํ ์ปดํฌ๋ํธ ๊ธฐ์ค)
๐ ์ปดํฌ๋ํธ, ๋ผ์ดํ ์ฌ์ดํด (ํด๋์คํ ! )
- componentDidMount : ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ๋จ, ์ฆ ์ปดํฌ๋ํธ์ ์ฒซ๋ฒ์งธ ๋ ๋๋ง์ด ๋ง์น๋ฉด ํธ์ถ๋๋ ๋ฉ์๋
componentDidMount() { console.log('Component has been mounted'); }
- componentDidUpdate : state์ ๋ณ๊ฒฝ, props์ ๋ณ๊ฒฝ ์ดํ ์คํ๋๋ ๋ฉ์๋
componentDidUpdate(prevProps, prevState, snapshot) { console.log('Component has been updated'); }
- componentWillUnmount : ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋๊ธฐ์ง์ (์ธ๋ง์ดํธ) ์์ ์ ์คํ๋๋ ๋ฉ์๋
componentWillUnmount() { console.log('Component will unmount'); }
- ์ด์ธ์๋ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์ต๋๋ค
๐บ ์ด๋, ์์ ์ค๋ช ํ componentDidMount ๊ฐ์ ์น๊ตฌ๋ค์ ` ํด๋์คํ ` ์์๋ง ์ฌ์ฉ๋๋ค.
`ํจ์ํ` ๋ ์์๋ณด์ !!!! !!!! !!!! !!!! !!!!
๐userEffect(์คํ์ํฌ ์ฝ๋ฐฑํจ์, ๊ฐ์ ๋ฐ๋ฅธ ๋ ๋๋ง ์ง์ -๋ฐฐ์ด )
ํจ์ํ ์ปดํฌ๋ํธ์์ ์ฌ์ด๋ ์ดํํธ(side effects)๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ํ ์ ๋๋ค.
์ฌ์ด๋ ์ดํํธ๋ ์ปดํฌ๋ํธ์ ๋ ๋๋ง ๊ณผ์ ์ธ๋ถ์์ ๋ฐ์ํ๋ ์์
- userEffect์ ์ฒซ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ ์คํ์ํฌ ์ฝ๋ฐฑํจ์
- userEffect์ ๋๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ ๋ฐฐ์ด[]์ ์ฌ์ฉํ์ฌ ํน์ ๊ฐ์ด update ๋ ๋๋ง ์คํ์์ผ ์ค ์ ์์ต๋๋ค.
- useEffect() ๋ ์ปดํฌ๋ํธ์ ๋ผ์ดํ ์ฌ์ดํด์ ๋ค๋ฃน๋๋ค. ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๊ฐ mount, mount์ดํ, unmount๋ ๋ง๋ค ํน์ ์์ ์ ์ํํฉ๋๋ค.
- useEffect() ๋ ์ฌ๋ฌ๊ฐ ์ผ ์๋ ์์ต๋๋ค.
- ๋ ๋๋ง(ํ๋ฉด์ ์ง์ ๋ค ๋ค์์์ฑ) ์ ์๋์ ๊ฐ์ ์ํฉ์ ๋ฐ์๋ฉ๋๋ค.
๐ ์ปดํฌ๋ํธ, ๋ผ์ดํ ์ฌ์ดํด (ํจ์ํ! )
1. ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ๋จ, ์ฆ ์ปดํฌ๋ํธ์ ์ฒซ๋ฒ์งธ ๋ ๋๋ง์ด ๋ง์น๋ฉด ํธ์ถ๋๋ ๋ฉ์๋
useEffect( () => {
console.log(`๋ ๋๋ง์๋ฃ`);
});
useEffect( () => {
console.log(`์ฒ์๋ง ์คํ๋ฉ๋๋ค`);
}, []);
//mount ์ดํ ์
๋ฐ์ดํธ ๋ ๋๋ ์คํ๋์ง ์์ผ๋ ค๋ฉด, ๋๋ฒ์งธ ๋งค๊ฐ๋ณ์ ๋ฐฐ์ด๋ฅผ ์ค๋๋ค.
2. state์ ๋ณ๊ฒฝ, props์ ๋ณ๊ฒฝ ์ดํ ์คํ๋๋ ๋ฉ์๋
const HookEffect = () => {
//useState
const[name, setName] = useState('');
const handleName = (e) => {
setName( e.target.value );
}
//ํน์ ๊ฐ์ด ์
๋ฐ์ดํธ ๋ ๋๋ง ์คํํด์ฃผ๋ ค๋ฉด ๋๋ฒ์งธ ๋งค๊ฐ๋ณ์์ ๊ฐ์ state๊ฐ์ ์ง์ ํฉ๋๋ค
useEffect( () => {
console.log(`name์ด ์
๋ฐ์ดํธ ์ ์คํ๋ฉ๋๋ค`)
}, [name]);
return (
<div>
์ด๋ฆ:<input type="text" onChange={handleName}/><br/>
์ด๋ฆ:{name}
</div>
)
}
export default HookEffect;
๐บโ ์ฃผ์ ) userEffect์์์ ๊ฐ์ฒดํ์ state๋ฅผ setStateํ๋ ๊ฒฝ์ฐ ๋ฌดํ๋ฃจํ์ ๋น ์ง ์ ์๋ค!
https://kinsta.com/knowledgebase/react-hook-useeffect-has-a-missing-dependency/
3. unmount์ง์ - ์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์์ ์ฌ๋ผ์ง๊ธฐ ์ง์ ์ ํธ์ถ๋ฉ๋๋ค.
const HookEffect = () => {
//useState
const[name, setName] = useState('');
const handleName = (e) => {
setName( e.target.value );
}
//useEffect
useEffect( () => {
console.log(`name์ด ์
๋ฐ์ดํธ ์ ์คํ๋ฉ๋๋ค`)
//unmount์ดํ ์คํ๋ฉ๋๋ค.
return () => {
console.log(`unmount์ ์คํ๋ฉ๋๋ค.`);
}
}, [name]);
return (
<div>
์ด๋ฆ:<input type="text" onChange={handleName}/><br/>
์ด๋ฆ:{name}
</div>
)
}
export default HookEffect;
3. ํน์ ํ๊ทธ์ ์ด๋ฆ๋ฌ๊ธฐ - useRef()
๐บ ์ด๋ฒคํธ ์ฌ์ฉํ๋ค๋ณด๋ฉด ํน์ ํ๊ทธ์ ์ ๊ทผํด์ ์ฒ๋ฆฌํด์ผํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธด๋ค.
๋ฌด์กฐ๊ฑด state ๋ก ๊ด๋ฆฌ๋์ด์ผ ์ ๊ทผ ๊ฐ๋ฅํ๋ฐ
state ๋ก ์ ์ด ์๋๋ ์ ๋ค์ (๋ค์ด๋ ํธ๋ก) ๋ค์ด๊ฐ์ ํธ๋ค๋ง์ ํด์ค๋ค.
์ด๋ ref ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
ref = {} ๋ก ๋ค์ด๋ ํธ๋ก ๋ฐ๋ก ์ ๊ทผํด์ ์ฌ์ฉํ ์ ์๋ค :)
๐ useRef() ํ
useRef(์ด๊ธฐ๊ฐ)
const ์ฌ์ฉํ ์ด๋ฆ = useRef(null);
- ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ๋ค ๋ณด๋ฉด ํน์ ํ๊ทธ์ ์ ๊ทผํด์ ํธ๋ค๋ง ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊น๋๋ค.
- arrow function์ event ๋งค๊ฐ๋ณ์๋ฅผ ์ด์ฉํด์, ์์ ํ๊ทธ์๋ ์ ๊ทผํ ์ ์์ง๋ง, ๋ค๋ฅธ ํ๊ทธ๋ ํธ๋ค๋ง ํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
- ์ด๋ฐ๊ฒฝ์ฐ useRef() ํ ์ ์ด์ฉํด์ ํน์ ํ๊ทธ์ ์ด๋ฆ์ ์ง์ ํ๊ณ ํธ๋ค๋ง ํ ์ ์์ต๋๋ค.
- useRef๋ ์ด๊ธฐ๊ฐ์ ๊ฐ์ฒด๋ก( {current:vlue} ) ์ ์ฅํ๊ธฐ๋๋ฌธ์ ๋ณ์๋ช .current๋ก ํ์ฌํ๊ทธ์ ์ ๊ทผ ํ ์์์ต๋๋ค.
import { useRef } from "react";
function HookRef(){
let input = useRef(null);
let handleClick = () => {
// ๊ฐ๋ณ๊ฒฝ์ state ๋ก ๊ด๋ฆฌํด์ฃผ๋ ๊ฒ์ด๊ณ (๋๋๋ง)
//ref ๋ ํน๋ณํ ์ํฉ์์๋ง ๊ฐ์ ๋ณ๊ฒฝ ์ ํธ๋์ง์์ (๋๋๋ง ์ผ์ด๋์ง ์์
//console.log(input);
//console.log(input.current); // ํ๊ทธ์ ๋ค์ด๋ ํธ ์ ๊ทผ ๊ฐ๋ฅ
console.log(input.current.type);
console.log(input.current.value);
input.current.focus();
}
return (
<>
<input type="text" ref={input}/>
<button type="button" onClick={handleClick}> ๋ฑ๋ก </button>
</>
)
}
export default HookRef;
4. ์ธ๋ถ์์ state์ฌ์ฉํ๊ธฐ - useReducer()
๐บ state ๋ฅผ ์ธ๋ถ์์ ์ฌ์ฉํ๊ณ ์ถ์๋์๋ ์ด๋ป๊ฒ ํด์ผํ ๊น?
useReducer() ํ ์ ์ฌ์ฉํ๋ฉด ๋๋ค !
๐ useReducer() ํ
- useReducer๋ state์ ๋น์ทํฉ๋๋ค.
- useReducer๋ ์ธ๋ถ์์ state๋ฅผ ๊ด๋ฆฌํ ์ ์๊ฒ ํด์ค๋๋ค.
- ๋ฆฌ๋์ํจ์๋ฅผ ์ธ๋ถ๋ก exportํ๊ฒ ๋๋ฉด ๋ก์ง์ ๋ถ๋ฆฌํ ์ ์์ต๋๋ค. (์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํด์ง)
- ์ฆ, ์ธ๋ถ์์ state ๊ด๋ฆฌํ ์ ์๊ฒ ํด์ค๋ค. ์ฌํ์ฉ์ด ๊ฐ๋ฅํด์ง๋ค.
const [ํ์ฌ๊ฐ, ๋ฆฌ๋์actionํจ์] = useReducer(๋ฆฌ๋์ํจ์๋ช
, state๊ฐ);
const ๋ฆฌ๋์ํจ์๋ช
= (state๊ฐ, ๋ฆฌ๋์actionํจ์๋ก ์ ๋ฌํ๋ ์ํ๊ฐ) => {
//์ด๊ธฐ๊ฐ์ action ์ํ์ ๋ฐ๋ผ์ ๋ณ๊ฒฝ
return state๊ฐ
}
import { useReducer } from "react";
//์ปดํฌ๋ํธ ์ธ๋ถ์ ์ ์ธ
//๋ฆฌ๋์(์ํ์ ์ด)๋ (ํ์ฌstate, ๋ฆฌ๋์actionํจ์๋ก ์ ๋ฌํ๋ ์ํ๊ฐ) ๋ฅผ ๋ฐ์ต๋๋ค.
const myReducer = (state, action) => {
if(action.type === 'increase') {
state = { value: state.value+1 }
} else if(action.type === 'decrease') {
state = { value: state.value-1 }
} else if(action.type === 'reset'){
state = { value : 0}
}
return state
}
const HookReducer = () => {
//state์์ ๋ง๋ค์๋ ์ฆ๊ฐ,๊ฐ์ ๋ฆฌ๋์ ์ ์ฉํ๊ธฐ
//1. const[state๊ฐ , ๋ฆฌ๋์์คํํจ์] useReducer( ๋ฆฌ๋์, state์ด๊ธฐ๊ฐ)
const [state, func] = useReducer(myReducer, {value:0 } )
const handleIncrease = () => {
func({type: 'increase'});
}
return (
<div>
<button type="button" onClick={ handleIncrease }>์ฆ๊ฐ</button>
<button type="button" onClick={ () => func({type: 'decrease'}) }>๊ฐ์</button>
<button type="button" onClick={ () => func({type: 'reset'}) }>์ด๊ธฐํ</button>
<br/>
ํ์ฌ์นด์ดํธ {state.value}
</div>
)
}
export default HookReducer;
๐ useState์ useReducer์ ๋น๊ต
- useState, useReducer ๋ชจ๋ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ํ ์ ๋๋ค.
- useState๋ ๊ด๋ฆฌํ ์ํ๊ฐ ๊ฐ๋จํ ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ฉด ์ข๋ค. (์ฝ๋ค)
- ๋ฐ๋ฉด ๊ด๋ฆฌํ ์ํ๊ฐ ์ฌ๋ฌ๊ฐ์ด๊ณ , ์๋ก๊ฐ ์์กดํ๊ณ ์์ผ๋ฉฐ, ์ํ๋ฅผ ์กฐ์ํ ๋์์ด ์ฌ๋ฌ๊ฐ์ผ ๋๋ useReducer๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค. (์ด๋ ต๋ค)
- ๋ฐ๋์ useReducer๋ฅผ ์จ์ผํ๋ ๊ฒ์ ์๋๋๋ค. useState๊ฐ ๋์ฒดํ ์ ์๊ฒ ๋๋ฌธ์ ๋๋ค.
[App.js]
import HookEffect from "./hook/HookEffect.js";
import HookQ2 from "./hook/HookQ2.js";
import HookReducer from "./hook/HookReducer.js";
import HookReducer2 from "./hook/HookReducer2.js";
import HookRef from "./hook/HookRef.js";
function App(){
return (
<>
<HookEffect />
<hr />
<HookRef />
<hr />
<HookReducer />
<hr />
<HookReducer2 />
<hr/>
<HookQ2 />
</>
)
}
export default App;
[HookEffect.js]
import {useEffect, useState} from 'react';
function HookEffect() {
//useStateํ
const [data, setData] = useState('');
const [age, setAge] = useState('');
//useEffectํ
=> ์ปดํฌ๋ํธ ๋ผ์ดํ์ฌ์ดํด ๊ด๋ฆฌ
useEffect( () => {
console.log('๋ง์ด๋ ์ดํ์ ๋์๋จ(๋ ๋๋ง ์ดํ์ ๋์)');
})
// useEffect( () => {
// console.log('๋ง์ด๋ ์ดํ์ ๋ฑ ํ๋ฒ๋ง ์คํ๋จ(๋คํธ์ํฌ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์ฌ๋ ์ฌ์ฉํจ)');
// }, []);
// useEffect( () => {
// console.log('ํน์ ๊ฐ์ด ๋ณ๊ฒฝ๋์ ๋ ๋๋ง ๋ ๋ ๋์๋จ(ํน์ state๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ์คํ๋จ)');
// }, [data, age]);
// useEffect( () => {
// console.log('effect์คํ๋จ~');
// return () => {
// console.log('unmount(์๋ฉธ) ๋๊ธฐ์ ์ ์คํ๋จ');
// }
// }, [data]); //data๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง.
//useEffect๋ ์ฌ๋ฌ๊ฐ ์ผ ์๋ ์์ต๋๋ค.
// useEffect( () => {
// console.log('effect์คํ๋จ22222~~');
// });
//๋ฌดํ๋ฃจํ์ ๋น ์ง ์ ์๋ ์ฝ๋
// const [ex, setEx] = useState({name : 'ํ๊ธธ๋'});
// useEffect( () => {
// let copy = {...ex};
// setEx(copy);
// }, [ex]);
console.log('์ฝ๋ ์คํ๋จ..');
return (
<>
<input type="text" value={data} onChange={ (e) => setData(e.target.value) } />
<br />
<input type="text" value={age} onChange={ (e) => setAge(e.target.value) }/>
data : {data} , age : {age}
</>
)
}
export default HookEffect;
useEffect( () => {
console.log('๋ง์ด๋ ์ดํ์ ๋์๋จ(๋ ๋๋ง ์ดํ์ ๋์)');
})
useEffect( () => {
console.log('๋ง์ด๋ ์ดํ์ ๋ฑ ํ๋ฒ๋ง ์คํ๋จ(๋คํธ์ํฌ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์ฌ๋ ์ฌ์ฉํจ)');
}, []);
useEffect( () => {
console.log('ํน์ ๊ฐ์ด ๋ณ๊ฒฝ๋ผ์ ๋ ๋๋ง ๋ ๋ ๋์๋จ(ํน์ state๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ์คํ๋จ)');
}, [data]);
- data ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง ์คํ๋๋ค.
useEffect( () => {
console.log('effect์คํ๋จ~');
});
useEffect( () => {
console.log('effect์คํ๋จ22222~~');
});
- useEffect ๋ ์ฌ๋ฌ๊ฐ ์กด์ฌํ ์ ์๋ค.
//๋ฌดํ๋ฃจํ์ ๋น ์ง ์ ์๋ ์ฝ๋
const [ex, setEx] = useState({name : 'ํ๊ธธ๋'});
useEffect( () => {
let copy = {...ex};
setEx(copy);
}, [ex]);
- ํด๋น ์ฝ๋๋ ๋ฌดํ๋ฃจํ์ ๊ฑธ๋ฆฌ๊ฒ๋๋ค.
- useEfftect() ๋ ex ๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ง๋ค ์คํ๋๋ค. => ํ์ง๋ง setEx() ๊ฐ ๊ณ์ํด์ ์คํ๋๋ฉด์ ex ๊ฐ ๊ณ์ ๋ฐ๋๋ฏ๋ก ๋ฌดํ๋ฃจํ๊ฒ ๊ฑธ๋ฆฌ๊ฒ ๋๋ค.
useEffect(() => {
let copy = { ...ex };
// ์ํ๊ฐ ์ค์ ๋ก ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง ์
๋ฐ์ดํธ
if (JSON.stringify(copy) !== JSON.stringify(ex)) {
setEx(copy);
}
}, [ex]);
- ์ด๋ฐ ๊ฒฝ์ฐ์๋ ์์ ๊ฐ์ด ์กฐ๊ฑด๋ฌธ์ผ๋ก ์ฒ๋ฆฌํด์ฃผ๋๊ฒ ๋ฌดํ๋ฃจํ๋ฅผ ๋ฐฉ์งํ๋๋ฐ ๋์์ด ๋๋ค.
[HookRef.js]
import { useRef } from "react";
function HookRef(){
let input = useRef(null);
let handleClick = () => {
// ๊ฐ๋ณ๊ฒฝ์ state ๋ก ๊ด๋ฆฌํด์ฃผ๋ ๊ฒ์ด๊ณ (๋๋๋ง)
//ref ๋ ํน๋ณํ ์ํฉ์์๋ง ๊ฐ์ ๋ณ๊ฒฝ ์ ํธ๋์ง์์ (๋๋๋ง ์ผ์ด๋์ง ์์
//console.log(input);
//console.log(input.current); // ํ๊ทธ์ ๋ค์ด๋ ํธ ์ ๊ทผ ๊ฐ๋ฅ
console.log(input.current.type);
console.log(input.current.value);
input.current.focus();
}
return (
<>
<input type="text" ref={input}/>
<button type="button" onClick={handleClick}> ๋ฑ๋ก </button>
</>
)
}
export default HookRef;
let input = useRef(null);
- useRef ๋ฅผ ํตํด input ์ด๋ผ๋ ์ฐธ์กฐ์์ฑ
console.log(input.current); // ํ๊ทธ์ ๋ค์ด๋ ํธ ์ ๊ทผ ๊ฐ๋ฅ
console.log(input.current.type);
console.log(input.current.value);
- useRef ๋ฅผ ํตํด์ ํ๊ทธ์ ๋ค์ด๋ ํธํ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
[HookReducer.js]
import { useReducer } from "react";
import { myReducer } from "../util/MyReducer";
function HookReducer() {
// // ๋ฆฌ๋์ ํจ์๋ ์ปดํฌ๋ํธ ์ธ๋ถ์์ ์ํ ๊ฐ์ ๋ฐ์์ state ์ฒด์ธ์ง !!!!!!!!!!!!!!!!!!!!
// const myReducer = (state, action) => {
// console.log(state);
// console.log(action);
if (action === "handleIncrease"){
state = {value : state.value + 1}; // state ๋ฅผ ๋ฐ์์ ๊ด๋ฆฌํ ์ ์๊ฒ๋จ
}else if (action === "decrease") {
state = {value : state.value - 1};
}else if (action === "reset") {
state = {value : 0};
}
// return state;//๋ฐํ๋๋ state ๋ reducer ์ํ๊ฐ์ผ๋ก ๋ค์ ๋ฐํ๋จ
// }; //state ๊ฐ , action (์ํ๊ฐ)
const handleIncrease = () => {
actionFunc("handleIncrease"); // myReducer ํจ์๋ก action ๋ค์ด๊ฐ
}
//const result = useReduce(myReducer,{value: 0} ); //๋ฆฌ๋์ ํจ์ ,์ด๊ธฐ๊ฐ
// ๋ฐํ, state ๊ฐ, reducerํจ์์ ์ํ๋ฅผ ๋ฐ๊ฟ ์ ์๋ action ํจ์
const [state, actionFunc] = useReducer(myReducer,{value: 0} ); //๋ฆฌ๋์ ํจ์ ,์ด๊ธฐ๊ฐ
//console.log(result);
return (
<>
<h3> useReducer</h3>
๋ฆฌ๋์๋ก ๊ด๋ฆฌ๋๋ state ๊ฐ {state.value}
<button type="button" onClick={handleIncrease} > ์ฆ๊ฐ </button>
<button type="button" onClick={() => actionFunc("decrease")} > ๊ฐ์ </button>
<button type="button" onClick={() => actionFunc("reset")} > ์ด๊ธฐํ </button>
</>
)
}
export default HookReducer;
const myReducer = (state, action) => {
console.log(state);
console.log(action);
return state;//๋ฐํ๋๋ state ๋ reducer ์ํ๊ฐ์ผ๋ก ๋ค์ ๋ฐํ๋จ
}; //state ๊ฐ , action (์ํ๊ฐ)
//----------
const [state, actionFunc] = useReducer(myReducer,{value: 0} ); //๋ฆฌ๋์ ํจ์ ,์ด๊ธฐ๊ฐ
//----------
<h3> useReducer </h3>
๋ฆฌ๋์๋ก ๊ด๋ฆฌ๋๋ state ๊ฐ {state.value}
- myReducer ์ํ ๊ด๋ฆฌ๋ฅผ ์ํด ์ฌ์ฉ๋๋ ํ ์ผ๋ก ์์ ๊ฐ์ด state, aciton ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๋ค.
- ์ฒซ๋ฒ์งธ ๋งค๊ฐ๋ณ์ : ๋ฆฌ๋์ ํจ์๋ก, ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ก์ง์ด๋ค! (state ๊ฐ์ ๋ค์ reducer ์ํ ๊ฐ์ผ๋ก ๋ฐํ๋จ)
- state: ํ์ฌ ์ํ ๊ฐ์ฒด
- action: ์ํ๋ฅผ ์ด๋ป๊ฒ ๋ณ๊ฒฝํ ์ง์ ๋ํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ ๊ฐ์ฒด
๋ฆฌ๋์๋ก ๊ด๋ฆฌ๋๋ state ๊ฐ {state.value}
<button type="button" onClick={handleIncrease} > ์ฆ๊ฐ </button>
<button type="button" onClick={() => actionFunc("decrease")} > ๊ฐ์ </button>
<button type="button" onClick={() => actionFunc("reset")} > ์ด๊ธฐํ </button>
- ๋ฒํผ์ ๋๋ฅด๋ฉด value ๊ฐ์ด ๋ณ๊ฒฝ๋๊ฒ ํ ๊ฒ ์ด๋ค.!
const handleIncrease = () => {
actionFunc("handleIncrease"); // myReducer ํจ์๋ก action ๋ค์ด๊ฐ
}
//onClick={() => actionFunc("decrease")}
// ์๊ฑฐ๋ ๊ฐ๋ค
const [state, actionFunc] = useReducer(myReducer,{value: 0} ); //๋ฆฌ๋์ ํจ์ ,์ด๊ธฐ๊ฐ
// actionFunc ๋ก ๋ค์ด๊ฐ๊ฒ๋๋ค
- actionFunc ์ handleIncrease or decrease ์ ๊ฐ์ ์ํ ๊ฐ์ ๋ฐ๋๋ค.
// ๋ฆฌ๋์ ํจ์๋ ์ปดํฌ๋ํธ ์ธ๋ถ์์ ์ํ ๊ฐ์ ๋ฐ์์ state ์ฒด์ธ์ง !!!!!!!!!!!!!!!!!!!!
const myReducer = (state, action) => {
console.log(state);
console.log(action);
if (action === "handleIncrease"){
state = {value : state.value + 1}; // state ๋ฅผ ๋ฐ์์ ๊ด๋ฆฌํ ์ ์๊ฒ๋จ
}else if (action === "decrease") {
state = {value : state.value - 1};
}else if (action === "reset") {
state = {value : 0};
}
return state;//๋ฐํ๋๋ state ๋ reducer ์ํ๊ฐ์ผ๋ก ๋ค์ ๋ฐํ๋จ
}; //state ๊ฐ , action (์ํ๊ฐ)
- ๋ฐ์์จ ์ํ๊ฐ์ ๋น๊ตํด์ state ๊ฐ์ ๋ณ๊ฒฝ์์ผ์ค๋ค.
- ์ดํ state ๊ฐ์ ๋ค์ ๋ฐํ์์ผ์ค๋ค !
[HookReducer2.js]
import { useReducer } from "react";
function HookReducer2(){
const nameReducer = (state, action) => {
//action์ ์ ๋ฌ๋๋ ๊ฐ์ ์๋ฆฌ๋จผํธ
state = {...state, [action.name] : action.value};
return state;
}
const [state, action] = useReducer(nameReducer,{name:'', age: 0} ); //๋ฆฌ๋์ ํจ์ ,์ด๊ธฐ๊ฐ
return (
<>
<input type="text" name="name" value={state.name} onChange={(e)=>action(e.target)}/>
<input type="number" name="age" value={state.age} onChange={(e)=>action(e.target)}/>
๋ฆฌ๋์๋ฅผ ํตํด์ญ ๋ณ๊ฒฝ๋ ๊ฐ : {state.name} {state.age}
</>
)
}
export default HookReducer2;
const [state, action] = useReducer(nameReducer,{name:'', age: 0} ); //๋ฆฌ๋์ ํจ์ ,์ด๊ธฐ๊ฐ
- ๋ฆฌ๋์ํจ์์ ์ด๊ธฐ๊ฐ์ ์ง์ ํด์ค๋ค. (state ์ action ์ผ๋ก ๋ฐํ๋๋ค)
- ์ฆ name ์ ๋น๊ฐ , age ๋ 0 ์ด ์ด๊ธฐ๊ฐ์ผ๋ก ์ค์ ๋๋ค.
const nameReducer = (state, action) => {
//action์ ์ ๋ฌ๋๋ ๊ฐ์ ์๋ฆฌ๋จผํธ
state = {...state, [action.name] : action.value};
return state;
}
- state ๊ฐ์ ๋ณต์ฌํด์์, action.name ์ ๊ฐ๋ง ๋ณ๊ฒฝํด์ฃผ๊ณ state ๋ฅผ ๋ฐํ์ํค๋ฉด
- ๋ค์ name ๊ณผ age ๊ฐ์ด ์ด๊ธฐ๊ฐ์ผ๋ก ์ค์ ๋๋ค.
[HookQ2.js]
import { useReducer, useRef, useState } from "react";
const HookQ2 = () => {
const [data, setData] = useState({todo:'', list : []});
const handleTodo = (e) => {
setData({...data, ["todo"] : e.target.value})
}
//ref
let input = useRef(null);
let handleClick = () => {
let newList = data.list;
newList.push(data.todo);
setData({todo: '', list : newList});
input.current.focus();
}
return (
<div>
<input type="text" name="todo" placeholder="ํ ์ผ ๋ชฉ๋ก ์์ฑ" ref={input} value={data.todo} onChange={handleTodo}/>
<button type="button" onClick={handleClick}> ๋ฑ๋ก </button>
<ul>
{
data.list.map((item,index) => <li key="index"> {index+1}. {item} </li>)
}
</ul>
</div>
)
}
export default HookQ2;
const [data, setData] = useState({todo:'', list : []});
const handleTodo = (e) => {
setData({...data, ["todo"] : e.target.value})
}
- todo, list ๊ฐ์ฒด ์์ฑ, ์ํ๊ด๋ฆฌ!
- handleTodo ๊ฐ ์คํ๋๋ฉด , todo ๊ฐ์ด input ๊ฐ์ผ๋ก ์ ๋ฐ์ดํธ ๋๋ค.
<input type="text" name="todo" placeholder="ํ ์ผ ๋ชฉ๋ก ์์ฑ" ref={input} value={data.todo} onChange={handleTodo}/>
<button type="button" onClick={handleClick}> ๋ฑ๋ก </button>
<ul>
{
data.list.map((item,index) => <li key="index"> {index+1}. {item} </li>)
}
</ul>
- ref ๋ useRef ๋ฅผ ํตํด input ์ ํฌ์ปค์ค๋ฅผ ๋ง์ถฐ์ฃผ๊ธฐ ์ํจ์ด๋ค.
let input = useRef(null);
let handleClick = () => {
let newList = data.list;
newList.push(data.todo);
setData({todo: '', list : newList});
input.current.focus();
}
- handClick ์ด ์๋ํ๋ฉด newList์ todo ๋ฅผ ์ถ๊ฐํ๊ณ setData ๋ก list ๋ฅผ newList๋ก ์ ๋ฐ์ดํธ ์์ผ์ค๋ค.
- input.current.focus(); ๋ก input ์ ํฌ์ปค์ค๋ฅผ ๋ง์ถฐ์ค๋ค.