함수 컴포넌트에서도 상태관리를 할 수 있는 작업
새 프로젝트로 만들기
$ yarn create react-app hooks-tutorial
주의 components 폴더 만들때 src안에 만들기
가장 기본적인 Hook이며, 함수 컴포넌트에서도 상태 관리가 가능하게 한다.
mport React,{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
클래스형으로 다시 만들기
import './App.css';
import Counter from './Components/Counter';
const App = () =>{
return (
<div className="App">
<Counter/>
</div>
)
}
export default App;
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>
<b>이름 :</b>{name}<br/>
<b>닉네임 :</b>{nickname}
</div>
</div>
)
}
export default Info
리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook
compoonentDidMount
+ componentDidUpdate
합한 형태로 볼 수 있다const [name,setName] = useState('')
const [nickname,setNickname] = useState('')
useEffect(()=>{
console.log('렌더링완료되었습니다.')
console.log({name,nickname})
})
렌더링, 즉 글자 한글자 칠 때마다 새로운 글이 올라온다.
useEffect(()=>{...},[])
useEffect(()=>{...},[name])
버튼 누르면 Info가 나타나게 하기 → 상태확인하기
useEffect(()=>{
console.log('effect.')
console.log(name)
return ()=>{
console.log('cleanup')
console.log(name)
}
},[name])
/App.js
const App = () =>{
const [visible,setVisible] = useState(false)
return (
<div className="App">
<Counter/>
<button
onClick={()=>{setVisible(!visible)}}
>{visible ? '숨기기':'보이기'}</button>
{visible && <Info/>}
</div>
)
}
useEffect(()=>{... return ()=>{..}},[name])
컴포넌트가 나타날 때, 값이 변할때 콘솔에 'effect'
가 나타나고, 사라질 때 'cleanup'
이 나타난다.
두번째 파라미터에 비어 있는 배열을 넣어라 ( name이 안바뀌니 출력이없다)
useEffect(()=>{... return ()=>{..}},[x])
useState
보다 더 다양한 컴포넌트 상황에서 다른값으로 업데이트 할 때 사용
현재 상태, 그리고 업데이트를 위해 필요한 정보를 담은 값을 전달받아 새 상태 반환하는 함수
불변성 지켜주기
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>현재 카운터값은 {state.value} 입니다.</p>
<button onClick={()=>dispatch({type:'DECREMENT'})}>-1</button>
<button onClick={()=>dispatch({type:'INCREMENT'})}>+1</button>
</div>
)
}
export default Counter
useReducer
의 첫번째 파라미터에는 리듀서 함수를 넣고, 두번째 파라미터에는 리듀서의 기본값을 넣어준다const [state,dispatch] = useReducer(reducer,{value:0})
state
값과 dispatch
함수를 받아오는데 , state
는 현재 가리키고 있는 상태고 dispatch
는 액션을 발생시키는 함수dispatch(action)
과 같은 형태로, 함수 안에 파라미터로 액션 값을 넣어주면 리듀서 함수 호출onClick={()=>dispatch({type:'DECREMENT'})}
인풋 태그에 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)}
...
<input name="name" value={name} onChange={onChange} />
onChange={onChange}
함수에서 e
에 name,value
를 함께 보내게 되고 action
의 값은 e.target
이고 , [action.name]:action.value
== [e.target.name] : e.target.value
가 되게 된다.