"firebase": "^9.6.6", 를 사용했습니다
파일의 구조는 다음과 같습니다.
: 파이어베이스 콘솔 세팅은 인터넷 세팅 및 유튜브에서 자세히 설명하고 있습니다.
: 나의 파이어베이스 프로젝트의 config 파일을 만들어주세요
: context를 만드는 파일입니다
: 파이어베이스에서 받은 값을 자식?들에게 전달해주는 컨텍스트를 만드는 파일입니다
에러가 많았던 파일
context 타입체크를 신경써야하는 파일
value에는 user와 setUser가 포함되어 있습니다.
user가 전달하고자 하는 핵심(파이어베이스 정보) 내용입니다.
export const UserContext = React.createContext<UserCxt | null>(null);
: 컨텍스트를 정의하는 부분입니다
: UserCxt는 인터페이스 입니다
interface UserCxt {
user: User;
setUser: (user: User) => void;
}
:user는 User 타입입니다. User는 firebase에서 import 한 것 입니다.
import { getAuth, onAuthStateChanged, User } from '@firebase/auth';
: 컨텍스트를 사용하기 위해 기초작업을 하는 파일입니다.
: useAuth가 감싸는 행위를 당하는? 파일입니다
: 감싼다는 의미는, useAuth가 value를 제공하는 Provider이기 때문에 감싼다는 표현을 사용했습니다
: 실제로 컨텍스트 value를 사용하는 파일입니다.
: UseAuth에서 전달한 값user을 실제적으로 사용하는 파일입니다.
import { initializeApp } from 'firebase/app';
interface lFire {
[key: string]: string | undefined;
}
const firebaseConfig: lFire = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
};
const app = initializeApp(firebaseConfig);
export { app };
: 사용자가 Firebase console에서 만든 프로젝트의 config값을 가져와서 이를 context로 만드는 파일
import React, { useEffect, useState } from 'react';
import { getAuth, onAuthStateChanged, User } from '@firebase/auth';
import { app } from './FirebaseConfig';
import { useNavigate } from 'react-router-dom';
interface UserCxt {
user: User;
setUser: (user: User) => void;
}
export const UserContext = React.createContext<UserCxt | null>(null);
export const defaultHeaders: any = {
'Content-Type': 'application/json',
Accept: 'application/json',
};
const hours = new Date().getHours();
const muninutes = new Date().getMinutes();
const UseAuth = ({ children }: { children: React.ReactNode }) => {
const navigate = useNavigate();
const auth = getAuth(app);
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (firebaseUser) => {
console.log('firebaseUser', firebaseUser);
if (firebaseUser) {
try {
const token = await firebaseUser.getIdToken();
defaultHeaders.Authorization = `Bearer ${token}`;
setUser(firebaseUser);
} catch (error) {
console.log('At UseAuth.tsx, Error is found', error);
}
} else {
delete defaultHeaders.Authorizations;
setUser(null);
}
});
return () => {
unsubscribe();
};
}, [auth, navigate]);
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
export default UseAuth;
=> UseAuth를 가지고 와서 Layout.tsx에 import 했습니다!
import { Outlet } from 'react-router';
import UseAuth from '../../Server/UseAuth';
import Logo from './Header/Logo/Logo';
import Navbar from './Header/Navbar/Navbar';
import FunctionsBtn from './Header/Utiles/FunctionBtn';
import {
Content,
Header,
HeaderSection,
HLeftSection,
HRightSection,
} from './Layout.style';
function Layout() {
return (
<>
<UseAuth>
<HeaderSection>
<Header>
<Content>
<HLeftSection>
<Logo />
<Navbar />
</HLeftSection>
<HRightSection>
<FunctionsBtn />
</HRightSection>
</Content>
</Header>
</HeaderSection>
<main>
<Content>
<Outlet />
</Content>
</main>
</UseAuth>
</>
);
}
export default Layout;
=>useContext 훅을 통해서 가져온 값, user의 값을 사용하고 있습니다
const { user } = useContext(UserContext);
import { RNav, RnItem, RnLi, RnList } from './FunctionsBtn.style';
import { useContext } from 'react';
import { UserContext } from '../../../../Server/UseAuth';
function FunctionsBtn() {
const { user } = useContext(UserContext);
console.log('뾰로롱~', user);
return (
<>
<RNav>
<RnList>
<RnLi>
{!user ? (
<RnItem to="/login" role="button">
Login
</RnItem>
) : (
<RnItem to="/logout" role="button">
Logout
</RnItem>
)}
</RnLi>
</RnList>
</RNav>
</>
);
}
export default FunctionsBtn;
does not exist on type 'jsx.intrinsicelements'
useAuth.tsx(변경 전) -> UseAuth.tsx (변경 후)
type 'IntrinsicAttributes & { children: any...
2번의 에러는
Logout.tsx 구조처럼
<UseAuth>
...중략...
</UseAuth>
UseAuth 가 context 이기 때문에 사용하기 위해서는 필요한 곳을 감싸야 한다, 위와 같은 구조로 덮은 상태에서
const UseAuth = () => {
이렇게 하니 발생한 에러입니다.
검색 중, 여기를 보고 힌트를 얻었습니다.
그래서 다음처럼 변경했습니다.
관련 부분
const UseAuth = ({ children }: { children: React.ReactNode }) => {
children의 대한 타입정의를 내려야 한다는 것입니다.
useAuth를 적용한 곳에서는 children을 사용하는데, children에 대한 정의가 없었습니다.
Cannot find namespace ...
당시, useAuth파일의 확장자를 .ts로 하고 있었다.
.tsx로 변경하니 해결됐다
관련 에러 해결은 여기에서 힌트를 얻어 해결했다.
{ children }: { children: React.ReactNode }
typescript로 컨텍스트시, children에게 value를 전달하기 때문에, children의 대한 타입을 정의해줘야 한다.
위의 형식은 여기 강좌와 여기, 벨로퍼트 님 블로그에서 힌트를 얻어 해결했습니다.
user는 Firebase의 값이 들어?오는 부분이라 초기에는 값이 null이다. 기가 막히게? null 이라고 하는 에러?다
사실, 나는
tsconfig.json에
"strictNullChecks": true,
를 하고 있었다.
초기에 null 이 되는게 정상?이라 생각해서, null을 살려?둬야 하기 때문에 null 체크 부분을 true로 해결했다.
"strictNullChecks": false,