DiaryApp - 새로운 일기 작성하기

dobyming·2023년 1월 28일
0

React Study

목록 보기
3/13

작동 방식

다음과 같이 사용자가 데이터를 입력 후, 저장 버튼을 누르면 리스트에 append 되는 기능을 구현 할 때 필요한 로직에 대해서 기록하고자 합니다.

구조 뜯어보기

현재 수행하고 있는 프로젝트는 다음과 같은 구조를 지니고 있습니다.

App.js : 부모 컴포넌트
DiaryEditor.js : 사용자가 일기를 입력하는 컴포넌트
DiaryList.js: 여러개의 일기를 List로 부모 컴포넌트 App.js에 렌더링 하는 컴포넌트

🤔 사용자 입력을 받아 리스트로 렌더링하여 부모 컴포넌트에 그려준다.
해당 부분을 구현하기 위해 생각이 드는 방향성은 DiaryEditor에서 작성한 현재 상태값 stateDiaryList에 넘겨서 App에 그리면 되는거 아닐까? 하는 생각이 들 수 있다.

결론은 불가하다.

즉 리액트는 같은 level에 있는 컴포넌트끼리는 데이터를 주고 받을 수 없는 단방향성의 흐름을 지니고 있다.

그러면 어떤 방안이 있을까 생각해보면 다음과 같이 다시 구조화 할 수 있다.

State 끌어올리기

오직 부모에서 자식으로 데이터를 보내는 단방향성의 흐름을 지니고 있는 리액트의 특징을 살려, App.js에서 useState를 활용하여 주고 받을 수 있다.

즉, 입력에 따라 상태를
변화시켜주는 setDataDiaryEditor로 넘겨서 새로운 일기를 작성하고
그리고 setting된 값을 data가 DiaryList의 props로 넘겨지는 구조이다.

그렇게 되면 위와 같은 흐름으로 사용자 입력에 따른 데이터와 이벤트 흐름의 구조가 이뤄진다. 리액트에서는 주로 이벤트는 역방향으로 데이터는 순방향으로 흐른다고 한다.

이는 곧 State 끌어올리기 라고 한다.

실제 코드

실제 코드로 살펴보며 어떻게 데이터와 이벤트가 driven 되는지 알아보자.

App.js 파일

const App = () => {
  const [data,setData] = useState([]); //현재 state인 data를 diaryList로 넘기고, 상태변화는 Editor에서 props로 넘겨져 이뤄진다.

  const dataId = useRef(0); //id를 리스트에 넘겨줘야 함 
	
  const onCreate = (author,content,emotion) => {
    const created_date = new Date().getTime();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      id: dataId.current
    }
    dataId.current += 1;
    setData([newItem,...data]); //newItem이 맨 위에 추가되도록 setData 매개변수로 전달
  };

  return (
    <div className="App">
      <DiaryEditor onCreate={onCreate}/> {/* 일기 작성 건들을 prop으로 넘겨줌 */}
      <DiaryList diaryList={data}/>
    </div>
  ); 
}

onCreate 함수는 사용자가 입력을 할때 상태값 data를 변화시켜주는 setDataDiaryEditor에 props로 넘겨주는 기능을 수행한다.

그리고 상태값 data는 리스트를 렌더링하는 DiaryList의 props로 넘겨진다.

DiaryEditor.js - props 처리하는 부분

const DiaryEditor = ({onCreate}) => {
    const [state,setState] = useState({
        author: "",
        content: "",
        emotion: 1,
    }); //작성자, 일기장 쓰는 state로직이 동일하므로 하나의 state로 관리
  
    /**
     * 일기 저장하기 버튼을 수행합니다.
     */
    const handleSubmit = () => {
        // 입력 validation check
        if(state.author.length < 1){
            authorInput.current.focus();
            return;
        }
        if(state.content.length < 5){
            contentInput.current.focus();
            return;
        }
        onCreate(state.author,state.content,state.emotion);
        alert('저장 성공');
    } 
};

onCreate를 props로 전달 받게 되고, 저장을 할때 리스트 렌더링이 필요하기 때문에 onCreate props를 handleSubmit()에서 호출하게 됩니다.

그러면 이렇게 다시 생각할 수 있습니다.

  1. DiaryEditor.js에서 저장버튼 클릭 시, 호출한 onCreate를 부모 컴포넌트 App.js에 넘긴다.
  2. 넘겨 받은 값을 newItem 객체 담은 후, setData로 현재 상태값인 data의 값을 변화시킨다.

지금까지 State 끌어올리기를 통해 컴포넌트 간 데이터를 주고 받는 과정을 살펴 보았습니다.

0개의 댓글