8.1 Hooks (useState,useEffect,useReducer)

hey hey·2021년 12월 11일
0

리액트 배우기

목록 보기
10/26
post-thumbnail

Hooks

함수 컴포넌트에서도 상태관리를 할 수 있는 작업

실습

새 프로젝트로 만들기

$ yarn create react-app hooks-tutorial

주의 components 폴더 만들때 src안에 만들기

useState

가장 기본적인 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;

useState 여러번 사용하기

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

useEffect

리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook

  • compoonentDidMount + componentDidUpdate 합한 형태로 볼 수 있다

전의 Info.js 에 useEffect 적용하기

const [name,setName] = useState('')
  const [nickname,setNickname] = useState('')
  useEffect(()=>{
    console.log('렌더링완료되었습니다.')
    console.log({name,nickname})
 })

렌더링, 즉 글자 한글자 칠 때마다 새로운 글이 올라온다.

1. 마운트될 때만 실행하고 싶을 때

  • 컴포넌트가 화면에 맨 처음 렌더링될 때만 실행하고, 업데이트 때는 실행하지 않게 하기
    • 두번째 파라미터로 비어 있는 배열을 넣어준다 useEffect(()=>{...},[])

2. 특정값이 업데이트될 때만 실행하고 싶을 때

  • 특정 값이 변경될 때만 호출하고 싶은 경우
    • 두번째 파라미터로 전달되는 배열 안에 검사하고 싶은 값 넣기 useEffect(()=>{...},[name])

3. 뒷정리하기

  • 컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떤 작업을 수행하고 싶다
    • 뒷정리(cleanup) 함수를 반환해야한다.

버튼 누르면 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])

useReducer (리덕스와 관련)

useState 보다 더 다양한 컴포넌트 상황에서 다른값으로 업데이트 할 때 사용

현재 상태, 그리고 업데이트를 위해 필요한 정보를 담은 값을 전달받아 새 상태 반환하는 함수

불변성 지켜주기

useReducer로 Counter 다시 만들어보기

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})
  • 이 Hook을 사용하면 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} />
  • reducer는 state 값에 action에 들어있는 name 변수(name,nickname)의 값을 action의 value로 하겠다.
  • onChange={onChange} 함수에서 ename,value 를 함께 보내게 되고 action의 값은 e.target이고 , [action.name]:action.value == [e.target.name] : e.target.value 가 되게 된다.
profile
FE - devp

0개의 댓글