개발🐕/React

[React Project: 간단한 일기장(完)] 컴포넌트 트리에 데이터 공급하기- Context

SU_VIN 2023. 1. 7. 16:28
반응형

 

 

 

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

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

www.inflearn.com

 

 

 

 

 

 

 

 

[React Project: 간단한 일기장(9)] 로직 분리하기 -useReducer

한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 - 인프런 | 강의 개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응

su-vin25.tistory.com

이어서...

 


두 번째 upgrade를 진행해볼 것이다

현재상태이다 보시다시피 onRemove()와 onEdit()은 DiaryList에서 쓰이지 않지만 DiaryItem에서 필요함으로

부모라는 이유만으로 Props drilling이 일어난다 그럼 유지보수에 힘들어지므로 이 부분을 업그레이드해볼 것이다

모든 데이터를 가지고 있는 컴포넌트가 Provider라는 공급자 역할를 하는 자식 컴포넌트에게 자신이 가지고있는

모든 데이터를 다 준다 그럼 이 Provider는 특별하게 자신의 자손에 해당하는 모든 컴포넌트들에게

직통으로 데이터를 보내줄 수 있다 즉 Props drilling이 없어지게 하는 것이다

 

이렇게 Provider컴포넌트의 자식 컴포넌트로 배치되어 Provider에서 제공하는 모든 데이터에 접근할 수 있는

이런 컴포넌트의 영역을 Context라고 한다

 

리액트의 context객체는 이런 식으로 생성한다

const MyContext = React.createContext(defaultValue);

그 후 이렇게 컴포넌트로 사용하면 된다

<MyContext.Provider value={전역으로 전달하고자하는 값}>
{/*이 context안에 위치할 자식 컴포넌트 들*/}
</Mycontext.Provider>

 

App.js에 넣어보자

export const DiaryStateContext = React.createContext();

export default는 파일에 하나밖에 못하기 때문에 그냥 export로 내보내 준다.

그 후 

  return (
    <DiaryStateContext.Provider value={data}>

    <div className="App">
    <DiaryEditor onCreate={onCreate}/>
    <div>전체일기 : {data.length}</div>
    <div>기분 좋은 일기 개수: {goodCount}</div>
    <div>기분 나쁜 일기 개수: {badCount}</div>
    <div>기분 좋은 일기 개수 비율: {goodRatio}</div>
    <DiaryList diaryList={data} onDelete={onDelete} onEdit={onEdit}/>
    </div>
          
    </DiaryStateContext.Provider>
  );

최상위 태그를 DiaryStateContext.Provider로 바꿔준다 다음 value값으로 data를 보내주면 된다

그럼 자식 컴포넌트들은 더 이상 data와 관련된 값들을 props로 받지 않아도 되는 것이다.

<DiaryList diaryList={data} onDelete={onDelete} onEdit={onEdit}/>

보면 DiaryList는 data를 prop으로 보내는데 이것을 더 이상 prop으로 보내지 않아도 된다는 것이다

<DiaryList onDelete={onDelete} onEdit={onEdit}/>

이렇게 prop을 지워주고

const DiaryList = ({onDelete,onEdit})=>{
    
    const diaryList = useContext(DiaryStateContext);

...
    )
}

이런 식으로 useContext를 data의 값을 공급받는다

 

그럼 같은 방식으로 onCreate, onDelete, onEdit 도 바꿔보자

 

export const DiaryDispatchContext = React.createContext();

function App() {
...

  const memoizedDispatches = useMemo(()=>{
    return{onCreate,onDelete,onEdit}
    
    return (
    <DiaryStateContext.Provider value={data}>
      <DiaryDispatchContext.Provider value={memoizedDispatches} >

...
      </DiaryDispatchContext.Provider>
    </DiaryStateContext.Provider>
  );
  },[])

context하나를 더 만들어주고 

onCreate, onDelete, onEdit를 리턴하는 useMemo로 감싼 memoizedDispatches 객체를 만들어

DiaryDispatchContext.Provider value값으로 보내준다

 

DiaryEditor

import React, { useContext, useEffect,useRef,useState } from "react";
import { DiaryDispatchContext } from "./App";

const DiaryEditor=()=>{
    
    const {onCreate} = useContext(DiaryDispatchContext)
...
}
export default React.memo(DiaryEditor);

prop을 지워주고 DiaryDispatchContext에서 useContext를 통해 onCreate를 받아준다

DiaryList

import { useContext } from "react";
import { DiaryStateContext } from "./App";
import DiaryItem from "./DiaryItem";

const DiaryList = ()=>{
    
    const diaryList = useContext(DiaryStateContext);

    return(
        <div className="DiaryList">
        <h2>일기 리스트</h2>
        <h4>{diaryList.length}개의 일기가 있습니다</h4>
        <div>
            {diaryList.map((it)=>(
                <DiaryItem key={it.id} {...it}/>
            ))}
        </div>
        </div>
    )
}

DiaryList.defaultProps={
    diaryList: [],
}


export default DiaryList;

DiaryItem

import React,{ useContext, useRef, useState } from "react";
import { DiaryDispatchContext } from "./App";

const DiaryItem=({
    author,
    content,
    emotion,
    created_date,
    id,
})=>{

    const{onDelete,onEdit}=useContext(DiaryDispatchContext);
...
}

export default React.memo(DiaryItem);

나머지도 다 같은 방식으로 고쳐보았다

 

이렇게 해서 리액트로 간단한 일기장 만들기가 완성되었다!

많은 리액트의 기능들을 배웠보았다!

끝.

반응형