초보 때 리액트 프로젝트를 하다보면 useDispatch와 useNavigate를 컴포넌트마다 선언 하게
되는 걸 볼 수 있다. 작업을 하다보면 이걸 한번만 선언하고 export 해서 쓸 순 없을까?
하는 생각이 매번 들었다. 그래서 실행해보기로 한다
👨💻 첫번째로 js파일을 따로 만들어 모듈을 뺄 생각을 해봤다.
import { useNavigate } from 'react-router-dom';
export const navigate = useNavigate(); // 잘못된 예시 - 최상위 레벨에서 호출하고 있음
function MyComponent() {
// 컴포넌트 내부의 다른 로직
}
실패
해당 에러가 뜬다.
React Hook "useNavigate" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks site:stackoverflow.com
🔎 오류해석
"useNavigate"가 올바르지 않은 위치에서 호출되었을 때 발생하며 React Hooks는 반드시 React 함수 컴포넌트나 사용자 지정 React Hook 함수 내에서 호출되어야 한다고 한다.
추가설명 ↓
React Hook은 컴포넌트의 렌더링 부분에서만 호출되어야 하며, 특히 함수 컴포넌트의 최상위 레벨에서만 호출되어야 한다. 만약 함수 컴포넌트 내에서 아닌 다른 곳에서 호출하면 이러한 규칙에 위배되므로 해당 오류가 발생한다고 한다.
올바른 예시)
import React from 'react';
import { useNavigate } from 'react-router-dom';
function MyComponent() {
const navigate = useNavigate();
// 이곳에서 navigate를 사용할 수 있음
return (
<div>
{/* 컴포넌트의 나머지 부분 */}
</div>
);
}
잘못된 예시)
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate(); // 잘못된 예시 - 최상위 레벨에서 호출하고 있음
function MyComponent() {
// 컴포넌트 내부의 다른 로직
}
🏃♂️🏃♀️ 챗 지피티 한테 열심히 물어보는중.....
답 => context API를 사용 하란다.
context API 사용하기
import React, { createContext } from "react";
createContext는 쉽게말해 context를 생성하는 기계이다.
createContext로 context를 만드는 방법은 전역으로 사용 하고 싶은 변수 또는 함수들을 객채에
넣어서 createContext의 파라미터로 넣는 것
import React, { createContext, useContext } from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
const useDefault = { navigate: () => {}, dispatch: () => {} }
const MyContext = createContext(useDefault);
💡 만든 createContext 사용 1-1
export const useMyContext = () => {
return useContext(myContext)
}
useContext라는 내장함수에 createContext 변수를 파라미터로 넣어주면 됨, 그리고 이걸 실행 시키기 위해 useMyContext라는 함수를 만들어서 하위 컴포넌트 들에서 이렇게 실행 해주면 된다.
import { useMyContext } from "../module/MyContext";
const { navigate, dispatch } = useMyContext();
💡 만든 createContext 사용 1-2
위 처럼 import 하고 컴포넌트마다 선언 하면 끝난 것 같지만 아직 한 단계가 남았다.
provider 생성해주기 react의 대부분의 전역관리 라이브러리들은 이 provider을 사용한다.
얘도 사용하는듯
export const MyContextProvider = ({ children }) => {
const navigate = useNavigate();
const dispatch = useDispatch();
// 여기서 미리 선언
return (
<MyContext.Provider value={{ navigate, dispatch }}>
// provider value에 props로 전송
{children} // layout 개념
</MyContext.Provider>
);
};
📖 context 전체코드
// MyContext.js (파일 생성)
import React, { createContext, useContext } from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
const MyContext = createContext({ navigate: () => {}, dispatch: () => {} });
export const MyContextProvider = ({ children }) => {
const navigate = useNavigate();
const dispatch = useDispatch();
return (
<MyContext.Provider value={{ navigate, dispatch }}>
{children}
</MyContext.Provider>
);
};
export const useMyContext = () => {
return useContext(MyContext);
};
이렇게 기본 셋팅을 해두고 필요한 컴포넌트에서 provider로 감싸주면 그 내부에선 전부 쓸 수 있게 된다.
// app.tsx
function components {
return (
<MyContextProvider>
code내용 ...///
</MyContextProvider>
)
}
사용 할 컴포넌트
import { useMyContext } from "../module/MyContext";
const { navigate, dispatch } = useMyContext();
// 불러오기