본문 바로가기
강의 실습/한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지

React에서 배열 사용하기 2 - 데이터 추가하기

by Jint 2024. 1. 16.

CREATE

1. React에서 리스트 데이터 추가하기
세부 목표)
- 배열을 이용한 React 의 List 에 아이템을 동적으로 추가해보기.
- With React 처럼 생각하기

* 컴포넌트 & 데이터 구조 생각해보기
리액트는 같은 레벨 간의 컴포넌트끼리 데이터를 주고 받는 일이 불가능하다. 윗 계층에서 아래 계층으로만 데이터를 보낼 수 있다. 즉 React 는 단방향으로만 데이터가 흐른다.
같은 계층으로 데이터를 주고받으려면, 각 컴포넌트의 state 를 공통 부모요소로 끌어올려 해결 가능하다.
일기장 프로젝트에 적용하면, App.js(부모 컴포넌트)에서 배열형식의 state 를 가지고 있고, props 로 각 자식컴포넌트인 DiaryList 와 DiaryEditor 에 데이터를 전달한다. DiaryList 에게 data 를 전달하여 List 형태로 데이터를 출력하고, DiaryEditor 에 setData 상태 변화 함수를 전달하여 새로운 일기를 작성하도록 한다. 이 때 추가된 data 가 EventList 에 props 으로 내려가며 리랜더링이 되어 추가된 리스트를 보여준다.

리액트로 만든 컴포넌트들은 트리 형태의 구조를 띄며 data 는 위에서 아래로만 움직이는 단방향 데이터 흐름이다. 추가, 수정, 삭제 등의 event 들은 데이터를 핸들링 하는 함수를 props 로 전달하여 아래에서 위로 올라가는 구조다.
여러개의 컴포넌트로 엮인 data 를 공통 부모 컴포넌트의 state 로 설정하여 문제 해결하는 방법을 state 끌어올리기 라고 할 수 있다.
state 끌어올리기, 단방향 data 흐름, 역방향 event 흐름을 활용해본다.

- App.js

import { useRef, useState } from 'react';
import './App.css';
import DiaryEditor from './DiaryEditor';
import DiaryList from './DiaryList';

// 임시 배열 데이터
/*
const dummyList = [
    {
        id: 1
      , author: '송진성'
      , content: '하이 1'
      , emotion: 5
      , created_date: new Date().getTime() // 현재 시간 기준 생성됨, getTime() : 시간을 밀리세컨트로 돌려줌
    }
  , {
        id: 2
      , author: '홍길동'
      , content: '하이 2'
      , emotion: 2
      , created_date: new Date().getTime()
    }
  , {
        id: 3
      , author: '아무개'
      , content: '하이 3'
      , emotion: 1
      , created_date: new Date().getTime()
    }
]
*/

function App() {

  const [data, setData] = useState([]); // 빈 배열로 시작 (일기가 없는 상태로 시작)

  const dataId = useRef(0);

  const onCreate = (author, content, emotion) => {
    const created_date = new Date().getDate();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      id: dataId.current
    }
    dataId.current += 1;
    setData([newItem, ...data]); // 위에서 부터 출력하기 위해 newItem, ...data 순서로 작성
  }
  console.log(typeof data);
  console.log(data);
  return (
    <div className="App">
      <DiaryEditor onCreate={onCreate}/>
      <DiaryList diaryList={data} />
    </div>
  );
}

export default App;


부모 컴포넌트에 state 배열을 만들고 각 자식 컴포넌트에게 props 를 전달한다. DiaryEditor 컴포넌트엔 onCreate 함수를(event), DiaryList 컴포넌트엔 data 를 전달한다.

- DiaryEditor.js

import { useState, useRef } from "react";

const DiaryEditor = ({ onCreate }) => {

    // DOM Element 접근
    const authorInput = useRef();
    const contentInput = useRef();

    // state 기본값 설정
    const [state, setState] = useState({
        author: ""
      , content: ""
      , emotion: 1
    })

    // 이벤트 함수
    const handleChangeState = (e) => {
        setState({
            ...state
          , [e.target.name]: e.target.value
        })
    }

    // 저장 함수
    const handleSubmit = () => {
        if (state.author.length < 1) {
            // alert('작성자는 최소 1글자 이상 입력해주세요.');
            // focus
            authorInput.current.focus();
            return;
        }
        if (state.content.length < 5) {
            // alert('일기 본문은 최소 5글자 이상 입력해주세요.');
            // focus
            contentInput.current.focus();
            return;
        }
        onCreate(state.author, state.content, state.emotion);
        alert('저장 성공!');
        // 저장 후 일기장 입력폼 초기화
        setState({
            author: ''
          , content: ''
          , emotion: 1
        })
    }

    return (
        <div className="DiaryEditor">
            <h2>오늘의 일기</h2>
            <div>
                <input
                    ref={authorInput}
                    name="author"
                    value={state.author}
                    onChange={handleChangeState}
                />
            </div>
            <div>
                <textarea
                    ref={contentInput}
                    name="content"
                    value={state.content}
                    onChange={handleChangeState}
                />
            </div>
            <div>
                <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>
            <div>
                <button onClick={handleSubmit}>일기 저장하기</button>
            </div>
        </div>
    )
  
}

export default DiaryEditor;


onCreate 함수를 props 로 전달받아 매개변수로 넣어준다. 이후 일기장 입력폼을 초기화 한다.

 

데이터 List에 추가

 

 

참고강의 : https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%EB%A6%AC%EC%95%A1%ED%8A%B8#

 

한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 강의 - 인프런

개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응용은 길게 17시간 분량의 All-in-one 강의!, 리액트, 한 강의로 끝장낼 수 있어요.

www.inflearn.com

댓글