profile image

L o a d i n g . . .

리액트 프로젝트 생성

npx create-react-app simplediary

 

 

 

불필요한 테스트, 로고이미지 지우고 App.js 임포트 정리까지 해줬다

 

 

 

 

 

 

 

 

 

 

오늘의 학습목표!

 

다양한 사용자 입력 처리하기

 

 

npm start  로 서버 구동

 

 

 

 

 

 


 

DiaryEditor 컴포넌트 생성

 

 

 

import './App.css';
import DiaryEditor from './DiaryEditor';

function App() {
  return (
    <div className="App">
      <h2>일기장</h2>
      <DiaryEditor></DiaryEditor>
    </div>
  );
}

export default App;

App.js에 임포트 해주고 서버 재구동하면

 

화면엔 안나오지만 F12 요소검사에서는 확인 할 수 있다

 

 

 

 

 

const DiaryEditor = () => {
    return (
    <div className="DiaryEditor">
        <h2> 오늘의 일기 </h2>
        <div>
            <input/>
        </div>
    </div>
    )
}

export default DiaryEditor;

App 컴포넌트에서 일기장 텍스트 삭제하고

DiaryEditor 컴포넌트를 수정해줬다.

input 태그는 한 줄 짜리 사용자 입력을 입력받을 수 있는 태그

 

 

이제 이 값을 DiaryEditor 컴포넌트가 핸들링 할 수 있도록 state를 사용한다

 

 

 

import { useState } from "react";

리액트 기능인 useState를 import 해준다.

 

 

 

작성자를 저장 할 것이기 때문에 

 const [author, setAuthor] = useState("");

useState기본값을 주고 author라는 state랑 author 상태변화를 주도할 setAuthor 상태변화함수까지 만들어주었다.

여기서 첫번째 값은 현재상태, 두번째 값은 Setter함수 이다

 

 

 

이제 input의 입력값이 바뀌면 입력값이 바뀔때마다 setAuthor 상태변화함수를 이용하여 author에 저장해줄것이다

 

input의 값을 author로 설정해준 후 input이 수정이 되면 author의 값을 실시간으로 바꿔줄 수 있는 이벤트를 추가한다

 

 

 

 

 

 


onChange

onChange 프롭에 이벤트객체e를 매개변수로 사용하는 콜백함수를 전달해준다.

            <input value={author} 
            onChange={(e)=>{
                console.log(e);
            }}/>

오늘의 일기 input에 값을 넣으려하면 console에 change 이벤트객체가 찍히게 된다

 

 

 

 

값을 직접 확인하려면 타겟의 value를 적은후 저장하면

콘솔에 input에 넣으려하는 값이 뜨게된다.

 

 

이제 직접 값을 넣어보자

 

import { useState } from "react";

const DiaryEditor = () => {

    const [author, setAuthor] = useState("");

    return (
    <div className="DiaryEditor">
        <h2> 오늘의 일기 </h2>
        <div>
            <input value={author} 
            onChange={(e)=>{
                setAuthor(e.target.value);
            }}/>
        </div>
    </div>
    )
}

export default DiaryEditor;

 

 

 

 


이번엔 한 줄 input 대신

여러 줄을 입력할 수 있는 textarea속성에 onChange이벤트를 사용해서 값을 전달해보자

import { useState } from "react";

const DiaryEditor = () => {

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

    return (
    <div className="DiaryEditor">
        <h2> 오늘의 일기 </h2>
        <div>
            <input value={author} 
            onChange={(e)=>{
                setAuthor(e.target.value);
            }}/>
        </div>
        <div>
            <textarea value={content} 
            onChange={(e)=> {
                setContent(e.target.value);
                console.log(e.target.value);
            }}/>
        </div>
    </div>
    )
}

export default DiaryEditor;

 

 

 

 

input과 textarea는 state를 이용하는 방법이 동일하다.

똑같이 value에 state 이름, onChange에 e.target.value를 상태변화함수에 전달, 두 값이 가지는 자료형까지 같다.

 

이럴땐 굳이 두 개의 state로 두지않고 하나로 묶을 수 있다.

 

import { useState } from "react";

const DiaryEditor = () => {

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

    return (
    <div className="DiaryEditor">
        <h2> 오늘의 일기 </h2>
        <div>
            <input value={state.author} 
            onChange={(e)=>{
                setState({
                    author: e.target.value,
                    content: state.content
                });
            }}/>
        </div>
        <div>
            <textarea value={state.content} 
            onChange={(e)=> {
                setState({
                    content: e.target.value,
                    author: state.author
                });
            }}/>
        </div>
    </div>
    )
}

export default DiaryEditor;

setState를 할 때 새로운 객체를 만들어서 변경 시켜준다

바뀔 부분은 값을 넣어주고, 유지해야할 부분은 state를 해준다.

 

 

 

 

하지만 2개가 아닌 인자가 10개 20개 일때는?

한 개만 바꾸려다가 너무 길어질 수 있다

이럴 때 사용하는게

            onChange={(e)=>{
                setState({
                    ...state,
                    author: e.target.value
                });
            }}/>

...state 같은 스프레드연산자

 

이때 주의해야 할 사항은

스프레드 연산자가 위로 가야한다.

스프레드연산자가 밑으로 가면 업데이트한 값이 다시 state로 변경되기 때문

 

 

 

 

input, textarea onChage이벤트도 중복이기 때문에 변수에 이벤트를 저장해준다

import { useState } from "react";

const DiaryEditor = () => {

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

    const handleChangeState = (e) => {
        console.log(e.target.name);
        console.log(e.target.value);
        setState({
            ...state,
            [e.target.name]: e.target.value
        })
    }

    return (
    <div className="DiaryEditor">
        <h2> 오늘의 일기 </h2>
        <div>
            <input name="author"
            value={state.author} 
            onChange={handleChangeState}/>
        </div>
        <div>
            <textarea name="content"
            value={state.content} 
            onChange={handleChangeState}/>
        </div>
    </div>
    )
}

export default DiaryEditor;

 

 

 

 

 

실시간으로 DiaryEditor 컴포넌트가 핸들링 할 수 있는 감정 선택 select 도 추가

 

너무 거슬려서 App.css 에 center 값 넣어줌

 

 

 

 

 

 

저장버튼을 만들어 폼에 입력한 값을 전달

    const handleSubmit = ()=>{
        console.log(state);
        alert("저장 성공");
    }
 <button onClick={handleSubmit}>일기 저장하기</button>

하단에 onClick이벤트를 넣은 버튼을 추가해주었다

 

 

 

 

 

 

입력 후 버튼을 클릭하면 콘솔창에 state를 이용해서 3개의 폼의 값을 확인할 수 있다

 

 

 

 

 

 

보기좋게 CSS 추가하고 span 태그로 select가 어떤 의미인지 입력해주기

.DiaryEditor {
  border: 1px solid gray;
  text-align: center;
  padding: 20px;
}

.DiaryEditor input, textarea {
  margin-bottom: 20px;
  width: 500px;
  padding: 10px;
}

.DiaryEditor textarea {
  height: 150px;
}

.DiaryEditor select {
  width: 300px;
  padding: 10px;
  margin-bottom: 20px;
}

.DiaryEditor button {
  width: 500px;
  padding: 10px;
  cursor: pointer;
}
import { useState } from "react";

const DiaryEditor = () => {

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

    const handleChangeState = (e) => {
        setState({
            ...state,
            [e.target.name]: e.target.value
        })
    }

    const handleSubmit = ()=>{
        console.log(state);
        alert("저장 성공");
    }

    return (
    <div className="DiaryEditor">
        <h2> 오늘의 일기 </h2>
        <div>
            <input name="author"
            value={state.author} 
            onChange={handleChangeState}/>
        </div>
        <div>
            <textarea name="content"
            value={state.content} 
            onChange={handleChangeState}/>
        </div>
        <div>
           <span> 오늘의 감정점수 : </span>
            <select name="emotion" 
            value={state.emotion}
            onChange={handleChangeState}>
                <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={handleSubmit}>일기 저장하기</button>
    </div>
    )
}

export default DiaryEditor;

 

 

 

 

 

쨔잔

 

 

 

 

 

 

 

참고 :

- 한 입 크기로 잘라먹는 리액트

- https://reactjs.org/docs/hooks-state.html

반응형
복사했습니다!