한입크기 리액트 일기장14. 컴포넌트 트리에 데어터 공급하기 - Context

임하나·2023년 2월 14일
0

한입크기리액트

목록 보기
16/21


Context 만드는 방법

export const DiaryStateContext = React.createContext();

DiaryStateContext 내보내주어야 다른 곳에서 쓸 수 있다.
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} onEdit={onEdit} onRemove={onRemove}/>
    </div>
</DiaryStateContext.Provider>
);

Provider 컴포넌트로 랩핑을 해준다.
value={data} 이런식으로 값(데이터)을 내려주어야한다.

DiaryList.js

import { useContext } from 'react';
import { DiaryStateContext } from './App';
const diaryList = useContext(DiaryStateContext);

useContext 으를 활용해 App.js 에서 내보냈던 DiaryStateContext 값을 가져와서, hooks 저장됨

그래서 더이상 App.js에서 diaryList를 props로 전달해줄 필요가 없다.

App.js

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

diaryList={data} 를 삭제해준다.

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

onEdit,onRemove context.Provider 만들어주자.
이때 주의 할 점은 기존처럼 <DiaryStateContext.Provider value={data}> onEdit,onRemove 값을 추가하면안된다.
Provider도 컴포넌트이기 때문에 data가 바뀌면 전부 리렌더링이 되어지기때문에 기존에 만든 최적화가 의미가 없어진다.
이럴경우 context.Provider를 중첩으로 사용하자
data값을 각각 따로 맞는다.

export const DiaryDispatchContext = React.createContext();
<DiaryStateContext.Provider value={data}>
  <DiaryDispatchContext.Provider>
  <div className="App">
    <DiaryEditor onCreate={onCreate} />
      <div>전체 일기 : {data.length}</div>
<div>기분 좋은 일기 개수 : {goodCount}</div>
<div>기분 나쁜 일기 개수 : {badCount}</div>
<div>기분 좋은 일기 비율 : {goodRatio}</div>
<DiaryList onEdit={onEdit} onRemove={onRemove}/>
  </div>
</DiaryDispatchContext.Provider>
</DiaryStateContext.Provider>


이런식으로 이중으로 감싸져있다.

onRemove, onEdit, onCreate값을 하나로 묶어서 전달하자.

const memoizedDispatches = useMemo(() => {
  return {onCreate, onRemove, onEdit}
},[]);

useMemo 를 사용해 재생성되지 않게 해준다.
만약 밑에 있는 것처럼, 값만 전달할경우 app컴포넌트가 재생성될때 dispatch 값도 재생성된다.

const dispatch = {
    onCreate, onRemove, onEdit
}
<DiaryStateContext.Provider value={data}>
  <DiaryDispatchContext.Provider value={memoizedDispatches}>
    <div className="App">
      <DiaryEditor onCreate={onCreate} />
        <div>전체 일기 : {data.length}</div>
<div>기분 좋은 일기 개수 : {goodCount}</div>
<div>기분 나쁜 일기 개수 : {badCount}</div>
<div>기분 좋은 일기 비율 : {goodRatio}</div>
<DiaryList onEdit={onEdit} onRemove={onRemove}/>
  </div>
</DiaryDispatchContext.Provider>
</DiaryStateContext.Provider>

기존에 있던 onCreate, onEdit, onRemove props를 삭제해준다.

<DiaryStateContext.Provider value={data}>
      <DiaryDispatchContext.Provider value={memoizedDispatches}>
        <div className="App">
          <DiaryEditor />
          <div>전체 일기 : {data.length}</div>
          <div>기분 좋은 일기 개수 : {goodCount}</div>
          <div>기분 나쁜 일기 개수 : {badCount}</div>
          <div>기분 좋은 일기 비율 : {goodRatio}</div>
          <DiaryList/>
        </div>
      </DiaryDispatchContext.Provider>
    </DiaryStateContext.Provider>

DiaryEditor.js

import React,{ useContext, useEffect, useState, useRef } from 'react';
import { DiaryDispatchContext } from './App.js';
const { onCreate } = useContext(DiaryStateContext);

객체로 전달됨으로 비구조화 할당으로 전달 받아야한다.

DiaryItem.js

import React,{ useContext, useEffect, useState, useRef } from 'react';
import { DiaryDispatchContext } from './App.js';
const { onRemove, onEdit } = useContext(DiaryDispatchContext);

기존에 prop으로 전달받았던 onRemove,onEdit 값은 삭제 해주어야한다.

0개의 댓글