useContext
useContext가 등장한 이유 (a.k.a React context)
→ 계속 컴포넌트를 통해 전달하는 것이 번거로움
→ useContext 등장
but 자주 남발하지 말 것
- Provider로 부터 Consumer까지 direct로 value(상태) 공유! (ex. App →→ Profile)
 - Provider의 Children들은 해당 context의 상태를 바로 접근 가능!
 - Context.Provider ~ Context.Consumer
 
useContext 사용하기
createContext(기본값): 컨텍스트 생성- 컴포넌트 외부에서 
createContext를 호출하여 컨텍스트를 생성 
- 컴포넌트 외부에서 
 SomeContext.Provider: 컨텍스트 영역 지정- createContext를 통해 생성한 컨텍스트의 범위를 Provider를 통해 지정
 - 컴포넌트를 컨텍스트 제공자로 감싸서 이 컨텍스트의 값을 모든 내부 컴포넌트에 지정
 - 쉽게 이해하기 ) 제공하는 쪽
 
SomeContext.Consumer: 컨텍스트 받기- 쉽게 이해하기 ) 사용하는 쪽
 
값을 공유하는 context
// context pattern 2 (provider-useContext)
export const MyContext = createContext();
render(
  <MyContext.Provider value={{xObj}}>
    <App />
  </MyContext.Provider>
);// context consumer by Provider + useContext
import { useContext } from 'react';
 
const { xObj } = useContext(MyContext);상태를 공유하는 context
- 
상태 변경 시, Provider는 물론, 모든 자식 컴포넌트(Consumer)는 모두 re-render됨
⇒ setState를 바로 공유하지 말고, 상태를 변경하는 함수를 전달하자!
ex) setCount (X) → plusCount 노출
 
BAD CODE
src/hooks/counter-context.tsx
// context pattern 3 (state-provider)  BAD!
type CounterContextProps = {
  count: number;
  setCount: Dispatch<SetStateAction<number>>;
};
 
const CounterContext = createContext<CounterContextProps>({
  count: 0,
  setCount: () => {},
});
 
export const CounterProvider = ({ children }: PropsWithChildren) => {
  const [count, setCount] = useState(0);
 
  return (
    <CounterContext.Provider value={{ count, setCount }}>
      {children}
    </CounterContext.Provider>
  );
};
 
// eslint-disable-next-line react-refresh/only-export-components
export const useCounter = () => useContext(CounterContext);src/main.tsx
// src/main.tsx - Provider
...
import { CounterProvider } from './hooks/counter-context.tsx';
 
ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <CounterProvider>
      <App />
    </CounterProvider>
  </React.StrictMode>
);GOOD CODE
src/hooks/counter-context.tsx
// pattern4 - src/hooks/counter-context.tsx    GOOD!
type CounterContextProps = {
  count: number;
  plusCount: () => void;
};
 
const CounterContext = createContext<CounterContextProps>({
  count: 0,
  plusCount: () => {},
});
 
export const CounterProvider = ({ children }: PropsWithChildren) => {
  const [count, setCount] = useState(0);
 
  const plusCount = () => setCount((count) => count + 1);
 
  return (
    <CounterContext.Provider value={{ count, **plusCount** }}>
      {children}
    </CounterContext.Provider>
  );
};
 
// eslint-disable-next-line react-refresh/only-export-components
export const useCounter = () => useContext(CounterContext);
 src/App.tsx
// Consumer
...
import { useCounter } from './hooks/counter-context';
 
function App() {
  const { count, plusCount } = useCounter();
 
  return (...);
}
export default App;
 사용 예시
./hooks/counter-context
import { createContext, PropsWithChildren, useContext, useState } from 'react';
 
type CounterContextProps = {
  count: number;
  plusCount: () => void;
};
 
const CounterContext = createContext<CounterContextProps>({
  count: 0,
  plusCount: () => {},
});
 
export const CounterProvider = ({ children }: PropsWithChildren) => {
  const [count, setCount] = useState(0);
  const plusCount = () => setCount((preCount) => preCount + 1);
  return (
    <CounterContext.Provider value={{ count, plusCount }}>
      {children}
    </CounterContext.Provider>
  );
};
 
export const useCounter = () => useContext(CounterContext);
 ./App.tsx
...
import { useCounter } from './hooks/counter-context';
 
function App() {
  const { count, plusCount } = useCounter();
	...
 
  return (
    <>
      <div className='card'>
        <button onClick={() => plusCount()}>count is {count}</button>
      </div>
    </>
  );
}
 
export default App;./main.tsx
...
import { CounterProvider } from './hooks/counter-context.tsx';
 
ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <CounterProvider>
      <App />
    </CounterProvider>
  </React.StrictMode>
);