React useState, useRef 알아보기

떡ol·2023년 8월 23일

useState란

React에서 상태(State)를 관리하기 위해 사용하는 Hook 중 하나인 useState() 는 함수형 컴포넌트에서 상태를 추가하고 변경할 수 있도록 하는 역할을 합니다.

예제 작성하기

Basic EX

useReact()를 사용하기 위해서는 react를 import해줘야합니다. 그리고 다음과 같이 함수형태로 선언을 해주시면 됩니다.
content가 변수가 되며, setContent가 setter가 됩니다.

import { useState } from "react";

const DiaryEditor = () => {
  const [content, setContent] = useState("");
  
  return (생략...)
}

export default DiaryEditor;

useState와 관계 없는 번외지만, DiaryEditor라는 함수가 곧 js파일명과 같게 됩니다. 이를 export하여 최종적으로 렌더링을 관장하는 App.js에 사용할 수 있게 됩니다.

Additional state

위에 코드를 실행해보면 아무런 입력도 되지 않으실겁니다.
React에 값을 변화시켜주기 위해서는 useState의 두번째 인자를 선언하여 setter가능 합니다.

import { useState } from "react";

const DiaryEditor = () => {
  const [author, setAuthor] = useState("디폴트");
  const [content, setContent] = useState("디폴트");
  
  return <div className="DiaryEditor">
        <h2>오늘의 일기</h2>
        <div>
            <input
                name="author"
                type="text"
                value={author}
                placeholder="직성자"
  				// onChange는 C가 대문자입니다.  react의 component를 사용하는 겁니다. 
                onChange = {(e) => { 
                    console.log(e.target.value);
                    setAuthor(e.target.value); 
                  // 다음과 같이 event에서 현재 타겟의 입력값을 가져와
                  //author변수에 넣어주게 됩니다. 
                }}
            />
        </div>

        <div>
            <textarea
                name="content"
                type="text"
                value={content}
                placeholder="일기"
                onChange = {(e) => {
                    console.log(e.target.value);
                    setContent(e.target.value);
                }}
            />
        </div>
	</div>
}

export default DiaryEditor;

useState 객체로 하나에 관리하기

다음의 코드는 사실 같은 기능을 하는 함수들입이니다 그냥 값과 setter로 구성되어있죠.

  const [author, setAuthor] = useState("디폴트");
  const [content, setContent] = useState("디폴트");

해당 useState는 다음과 같이 표현 가능합니다.

  const [state, setState] = useState({
        author: "",
        content: "",
    })

마찬가지로 onCange함수, value도 다음과 같이 표현이 가능해집니다.

	value={state.author} // 이것도 변경해야합니다.

    onChange = {(e) => {
        console.log(e.target.value);
        //setAuthor(e.target.value); //1
        setState({  //2
            author: e.target.value,
            content: state.content,
        })

해당함수는 spread 표현식으로 다음과 같이 최적화가능합니다.

    onChange = {(e) => {
        console.log(e.target.value);
        // setState({  //2
        //     author: e.target.value,
        //     content: state.content,
        // })
        setState({  //3
            ...state,
            author: e.target.value,
        })
    }}

함수로 관리하기

당연하겠지만 onChange를 공통으로 사용가능하게 Handler를 하나 제작해줍시다.
setState()function 묶어 사용하시고 (Arrow function으로 해도 됩니다.)
괄호표기법으로 target을 event 단위로 셋팅하게 맞춰주시면 됩니다.

    function ChangeHandler(e) {
        setState({
            ...state,
            [e.target.name]: e.target.value,
        });
    }

이렇게 되면 target이 되는 input tag에 naming을 해줘야 겠죠? 우리는 위에서 이미 작성을 해왔기 때문에 별다른 수정은 필요없습니다.

<input name="author'/>
<textarea name="content"/>

그리고 JSX의 onChange부분에서 함수실행을 하면 됩니다.

<input
	name="author"
	type="text"
	value={state.author}
	onChange={ChangeHandler} // 요기 수정
	placeholder="직성자"/>

uesRef란

리액트에서는 DOM 노드나 React 엘리먼트에 접근하기 위한 방법으로 Ref라는 API를 제공합니다.

예제 작성하기

다음과 같이 useRef()를 선언해주시고 어떤 엘리먼트에 접근할건지 해당 노드에 선언해주시면 됩니다. 마찬가지로 react 줄에 import해줍니다.

    const authorInput = useRef();
    const contentInput = useRef();
    
	// 중략...
    
   <input
      ref={authorInput}
      name="author"
      type="text"
      value={state.author}
      onChange={ChangeHandler}
      placeholder="직성자"/>

이제 우리는 author엘리먼트에 접근할 수 있는 방법이 생겼습니다. input에 입력이 없으면 focus를 발생하는 간단한 script를 작성해봅니다.

    const SubmitHandler = () => {
        if(state.author.length < 1) {
            authorInput.current.focus();
            return;
        }
        if(state.content.length < 1) {
            contentInput.current.focus();
            return;
        }

        console.log(state);
        alert("save complete!");
        setState({
            author: "",
            content: ""
        }) // 저장하고 초기화하기위한...
    };

완성

emotion을 추가하여 만들었습니다. App.js에도 <DiaryEditor />추가해주시면 됩니다.

import {useRef, useState} from "react";

const DiaryEditor = ({onCreate}) => {
    const authorInput = useRef();
    const contentInput = useRef();

    const [state, setState] = useState({
        author: "",
        content: "",
        emotion: 1,
    })

    //const [author, setAuthor] = useState("디폴트");
    //const [content, setContent] = useState("디폴트");

    function ChangeHandler(e) {
        setState({
            ...state,
            [e.target.name]: e.target.value,
        });
    }

    const SubmitHandler = () => {
        if(state.author.length < 1) {
            authorInput.current.focus();
            return;
        }
        if(state.content.length < 1) {
            contentInput.current.focus();
            return;
        }
        onCreate(state.author, state.content, state.emotion);
        console.log(state);
        alert("save complete!");
        setState({
            author: "",
            content: "",
            emotion: 1
        })
    };

    return <div className="DiaryEditor">
        <h2>오늘의 일기</h2>
        <div>
            <input
                ref={authorInput}
                name="author"
                type="text"
                value={state.author}
                onChange={ChangeHandler}
                placeholder="직성자"
            />
        </div>

        <div>
            <textarea
                ref={contentInput}
                name="content"
                type="text"
                value={state.content}
                onChange={ChangeHandler}
                placeholder="일기"
            />
        </div>
        <div>
            <span>오늘의 감정점수 : </span>
            <select name="emotion"
                value={state.emotion}
                onChange={ChangeHandler}>
                <option value={1}>1</option>
                <option value={2}>2</option>
                <option value={3}>3</option>
                <option value={4}>4</option>
                <option value={5}>5</option>

            </select>
        </div>
        <button onClick={SubmitHandler}>save</button>
    </div>;
};
export default DiaryEditor;

참고자료들___
(참고) 한입 크기로 잘라 먹는 리엑트(React.js) : 기초부터 실천까지

profile
하이

0개의 댓글