Firebase 리스너를 사용하여 클라우드 Firestore 데이터가 반응 후크 업데이트로 새로 고쳐지는 방법을 알아 내려고합니다.
처음에는 componentDidMount 함수와 함께 클래스 구성 요소를 사용하여 firestore 데이터를 가져 왔습니다.
this.props.firebase.db
.collection('users')
// .doc(this.props.firebase.db.collection('users').doc(this.props.firebase.authUser.uid))
.doc(this.props.firebase.db.collection('users').doc(this.props.authUser.uid))
.get()
.then(doc => {
this.setState({ name: doc.data().name });
// loading: false,
});
}
페이지가 업데이트되면 중단되므로 리스너를 이동하여 후크를 반응시키는 방법을 알아 내려고합니다.
react-firebase-hooks 도구를 설치 했지만 작동시키는 지침을 읽는 방법을 알 수는 없지만.
다음과 같은 함수 구성 요소가 있습니다.
import React, { useState, useEffect } from 'react';
import { useDocument } from 'react-firebase-hooks/firestore';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
useRouteMatch,
} from 'react-router-dom';
import * as ROUTES from '../../constants/Routes';
import { compose } from 'recompose';
import { withFirebase } from '../Firebase/Index';
import { AuthUserContext, withAuthorization, withEmailVerification, withAuthentication } from '../Session/Index';
function Dashboard2(authUser) {
const FirestoreDocument = () => {
const [value, loading, error] = useDocument(
Firebase.db.doc(authUser.uid),
//firebase.db.doc(authUser.uid),
//firebase.firestore.doc(authUser.uid),
{
snapshotListenOptions: { includeMetadataChanges: true },
}
);
return (
<div>
<p>
{error && <strong>Error: {JSON.stringify(error)}</strong>}
{loading && <span>Document: Loading...</span>}
{value && <span>Document: {JSON.stringify(value.data())}</span>}
</p>
</div>
);
}
}
export default withAuthentication(Dashboard2);
이 구성 요소는 다음과 같이 경로 수준에서 authUser 래퍼로 래핑됩니다.
<Route path={ROUTES.DASHBOARD2} render={props => (
<AuthUserContext.Consumer>
{ authUser => (
<Dashboard2 authUser={authUser} {...props} />
)}
</AuthUserContext.Consumer>
)} />
firebase.js 파일이 있는데 다음과 같이 firestore에 연결됩니다.
class Firebase {
constructor() {
app.initializeApp(config).firestore();
/* helpers */
this.fieldValue = app.firestore.FieldValue;
/* Firebase APIs */
this.auth = app.auth();
this.db = app.firestore();
}
또한 authUser가 언제 변경되는지 알 수있는 리스너를 정의합니다.
onAuthUserListener(next, fallback) {
// onUserDataListener(next, fallback) {
return this.auth.onAuthStateChanged(authUser => {
if (authUser) {
this.user(authUser.uid)
.get()
.then(snapshot => {
let snapshotData = snapshot.data();
let userData = {
...snapshotData, // snapshotData first so it doesn't override information from authUser object
uid: authUser.uid,
email: authUser.email,
emailVerified: authUser.emailVerifed,
providerData: authUser.providerData
};
setTimeout(() => next(userData), 0); // escapes this Promise's error handler
})
.catch(err => {
// TODO: Handle error?
console.error('An error occured -> ', err.code ? err.code + ': ' + err.message : (err.message || err));
setTimeout(fallback, 0); // escapes this Promise's error handler
});
};
if (!authUser) {
// user not logged in, call fallback handler
fallback();
return;
}
});
};
그런 다음 내 Firebase 컨텍스트 설정에 다음이 있습니다.
import FirebaseContext, { withFirebase } from './Context';
import Firebase from '../../firebase';
export default Firebase;
export { FirebaseContext, withFirebase };
컨텍스트는 다음과 같이 withFirebase 래퍼에서 설정됩니다.
import React from 'react';
const FirebaseContext = React.createContext(null);
export const withFirebase = Component => props => (
<FirebaseContext.Consumer>
{firebase => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
export default FirebaseContext;
그런 다음 with with Authorization HOC에서 다음과 같은 컨텍스트 공급자가 있습니다.
import React from 'react';
import { AuthUserContext } from '../Session/Index';
import { withFirebase } from '../Firebase/Index';
const withAuthentication = Component => {
class WithAuthentication extends React.Component {
constructor(props) {
super(props);
this.state = {
authUser: null,
};
}
componentDidMount() {
this.listener = this.props.firebase.auth.onAuthStateChanged(
authUser => {
authUser
? this.setState({ authUser })
: this.setState({ authUser: null });
},
);
}
componentWillUnmount() {
this.listener();
};
render() {
return (
<AuthUserContext.Provider value={this.state.authUser}>
<Component {...this.props} />
</AuthUserContext.Provider>
);
}
}
return withFirebase(WithAuthentication);
};
export default withAuthentication;
현재 이것을 시도하면 Dashboard2 구성 요소에 다음과 같은 오류가 발생합니다.
Firebase ‘가 정의되지 않았습니다
소문자 firebase를 시도했지만 동일한 오류가 발생합니다.
firebase.firestore 및 Firebase.firestore도 시도했습니다. 같은 오류가 발생합니다.
HOC를 함수 구성 요소와 함께 사용할 수 없는지 궁금합니다.
블로그의 조언에 따라 새로운 firebase / contextReader.jsx를 만들었습니다.
import React, { useEffect, useContext } from 'react';
import Firebase from '../../firebase';
export const userContext = React.createContext({
user: null,
})
export const useSession = () => {
const { user } = useContext(userContext)
return user
}
export const useAuth = () => {
const [state, setState] = React.useState(() =>
{ const user = firebase.auth().currentUser
return { initializing: !user, user, }
}
);
function onChange(user) {
setState({ initializing: false, user })
}
React.useEffect(() => {
// listen for auth state changes
const unsubscribe = firebase.auth().onAuthStateChanged(onChange)
// unsubscribe to the listener when unmounting
return () => unsubscribe()
}, [])
return state
}
그런 다음 App.jsx를 해당 리더로 래핑하려고합니다.
function App() {
const { initializing, user } = useAuth()
if (initializing) {
return <div>Loading</div>
}
// )
// }
// const App = () => (
return (
<userContext.Provider value={{ user }}>
<Router>
<Navigation />
<Route path={ROUTES.LANDING} exact component={StandardLanding} />
이것을 시도하면 다음과 같은 오류가 발생합니다.
TypeError : _firebase__WEBPACK_IMPORTED_MODULE_2 __. default.auth는 함수가 아닙니다
내가 본 이 게시물 이 오류 처리 및 제거하고 실을 다시 설치 시도했다. 차이가 없습니다.
데모 앱을 살펴보면 ‘인터페이스’방법을 사용하여 컨텍스트를 만들어야한다고 제안합니다. 이것이 어디에서 왔는지 알 수 없습니다-설명서에서 설명하는 참조를 찾을 수 없습니다.
나는 이것을 연결하기 위해 한 것을 시도하는 것 이외의 지시를 이해할 수 없다.
react-firebase-hook을 사용하지 않고 firestore를 청취하려는 이 게시물 을 보았습니다 . 답은이 도구를 사용하는 방법을 알아 내려고하는 것입니다.
HOC에서 후크로 이동하는 방법에 대한 훌륭한 설명 을 읽었습니다 . Firebase 리스너를 통합하는 방법에 갇혀 있습니다.
나는이 일을 생각하는 방법에 대한 유용한 예를 제공하는 이 게시물 을 보았습니다 . authListener componentDidMount 또는이를 사용하려는 대시 보드 구성 요소에서이 작업을 수행해야하는지 확실하지 않습니다.
다음 공격
나는 이 게시물을 찾았 는데, 같은 문제를 해결하려고합니다.
Shubham Khatri가 제공하는 솔루션을 구현하려고 할 때 다음과 같이 firebase 구성을 설정했습니다.
import React, {useContext} from ‘react’; ‘../../firebase’에서 Firebase 가져 오기;
const FirebaseContext = React.createContext();
export const FirebaseProvider = (props) => (
<FirebaseContext.Provider value={new Firebase()}>
{props.children}
</FirebaseContext.Provider>
);
컨텍스트 후크는 다음과 같습니다.
import React, { useEffect, useContext, useState } from 'react';
const useFirebaseAuthentication = (firebase) => {
const [authUser, setAuthUser] = useState(null);
useEffect(() =>{
const unlisten =
firebase.auth.onAuthStateChanged(
authUser => {
authUser
? setAuthUser(authUser)
: setAuthUser(null);
},
);
return () => {
unlisten();
}
});
return authUser
}
export default useFirebaseAuthentication;
그런 다음 index.js에서 공급자의 앱을 다음과 같이 랩핑합니다.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App/Index';
import {FirebaseProvider} from './components/Firebase/ContextHookProvider';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<FirebaseProvider>
<App />
</FirebaseProvider>,
document.getElementById('root')
);
serviceWorker.unregister();
그런 다음 구성 요소에서 리스너를 사용하려고하면 다음이 있습니다.
import React, {useContext} from 'react';
import { FirebaseContext } from '../Firebase/ContextHookProvider';
import useFirebaseAuthentication from '../Firebase/ContextHook';
const Dashboard2 = (props) => {
const firebase = useContext(FirebaseContext);
const authUser =
useFirebaseAuthentication(firebase);
return (
<div>authUser.email</div>
)
}
export default Dashboard2;
그리고 구성 요소 또는 인증 래퍼가없는 경로로 사용하려고합니다.
<Route path={ROUTES.DASHBOARD2} component={Dashboard2} />
이것을 시도하면 다음과 같은 오류가 발생합니다.
가져 오기 오류가 발생했습니다 : ‘../Firebase/ContextHookProvider’에서 ‘FirebaseContext’를 내 보내지 않았습니다.
이 오류 메시지는 ContextHookProvider가 FirebaseContext를 내 보내지 않기 때문에-FirebaseProvider를 내 보내지 만-Dashboard2에서 가져 오려고 시도하지 않으면 사용하려고하는 함수에서 액세스 할 수 없습니다.
이 시도의 부작용 중 하나는 가입 방법이 더 이상 작동하지 않는다는 것입니다. 이제 다음과 같은 오류 메시지가 생성됩니다.
TypeError : null의 ‘doCreateUserWithEmailAndPassword’속성을 읽을 수 없습니다
나중에이 문제를 해결할 것입니다.하지만 기본 인증 설정을 수행 할 수없는 수백만 번의 경로를 통해이 루프를 수개월 동안 수행하지 않는 firebase와 반응하는 방법을 알아낼 수있는 방법이 있어야합니다. 반응 고리와 작동하는 firebase (firestore) 용 스타터 키트가 있습니까?
다음 시도
는이 udemy 과정 의 접근법을 따르려고 시도 했지만 양식 입력 만 생성합니다. 인증 된 사용자와 조정하기 위해 경로 주위에 리스너가 없습니다.
이 YouTube 자습서 의 접근 방식을 따르려고했습니다 . 이 레포 가 작동합니다. 후크를 사용하는 방법을 보여 주지만 컨텍스트를 사용하는 방법은 보여주지 않습니다.
다음 공격
나는 소방서에 후크를 사용하는 방법을 잘 알고있는 이 레포 를 발견 했습니다 . 그러나 코드를 이해할 수 없습니다.
나는 이것을 복제하고 모든 공개 파일을 추가하려고 시도한 다음 실행할 때 실제로 코드를 작동시킬 수 없습니다. 이 문제를 해결하는 데 도움이되는 코드에 교훈이 있는지 확인하기 위해이를 실행하는 방법에 대한 지침에서 누락 된 것이 무엇인지 잘 모르겠습니다.
다음 공격
나는 divjoy 템플릿을 구입했는데 firebase에 대한 설정으로 광고됩니다 (다른 사람이 이것을 옵션으로 고려할 경우 firestore에 대해서는 설정되지 않았습니다).
이 템플릿은 앱의 구성을 초기화하는 인증 래퍼를 제안하지만 인증 메소드에 대해서만 다른 컨텍스트 제공자가 firestore를 사용할 수 있도록 재구성해야합니다. 해당 프로세스를 방해 하고이 게시물에 표시된 프로세스를 사용하면 남은 것은 다음 콜백의 오류입니다.
useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged(user => {
if (user) {
setUser(user);
} else {
setUser(false);
}
});
Firebase가 무엇인지 알 수 없습니다. 이는 (proProdedeAuth () 함수에서) 가져오고 정의 된 firebase 컨텍스트 제공자에 다음과 같이 정의되어 있기 때문입니다.
const firebase = useContext(FirebaseContext)
콜백 기회가 없으면 오류는 다음과 같이 표시됩니다.
React Hook useEffect의 종속성이 누락되었습니다 : ‘firebase’. 포함 시키거나 종속성 배열을 제거하십시오.
또는 콜백에 해당 const를 추가하려고하면 다음과 같은 오류가 발생합니다.
콜백 내에서 React Hook “useContext”를 호출 할 수 없습니다. React Hook는 React 함수 구성 요소 또는 사용자 정의 React Hook 함수에서 호출해야합니다.
다음 공격
내 firebase 설정 파일을 설정 변수로 줄였습니다 (사용하려는 각 컨텍스트에 대해 컨텍스트 제공자에 도우미를 작성합니다).
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
const devConfig = {
apiKey: process.env.REACT_APP_DEV_API_KEY,
authDomain: process.env.REACT_APP_DEV_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_DEV_DATABASE_URL,
projectId: process.env.REACT_APP_DEV_PROJECT_ID,
storageBucket: process.env.REACT_APP_DEV_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_DEV_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_DEV_APP_ID
};
const prodConfig = {
apiKey: process.env.REACT_APP_PROD_API_KEY,
authDomain: process.env.REACT_APP_PROD_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_PROD_DATABASE_URL,
projectId: process.env.REACT_APP_PROD_PROJECT_ID,
storageBucket: process.env.REACT_APP_PROD_STORAGE_BUCKET,
messagingSenderId:
process.env.REACT_APP_PROD_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_PROD_APP_ID
};
const config =
process.env.NODE_ENV === 'production' ? prodConfig : devConfig;
class Firebase {
constructor() {
firebase.initializeApp(config);
this.firebase = firebase;
this.firestore = firebase.firestore();
this.auth = firebase.auth();
}
};
export default Firebase;
그런 다음 다음과 같이 인증 컨텍스트 제공자가 있습니다.
import React, { useState, useEffect, useContext, createContext } from "react";
import Firebase from "../firebase";
const authContext = createContext();
// Provider component that wraps app and makes auth object ...
// ... available to any child component that calls useAuth().
export function ProvideAuth({ children }) {
const auth = useProvideAuth();
return <authContext.Provider value={auth}>{children}</authContext.Provider>;
}
// Hook for child components to get the auth object ...
// ... and update when it changes.
export const useAuth = () => {
return useContext(authContext);
};
// Provider hook that creates auth object and handles state
function useProvideAuth() {
const [user, setUser] = useState(null);
const signup = (email, password) => {
return Firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(response => {
setUser(response.user);
return response.user;
});
};
const signin = (email, password) => {
return Firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(response => {
setUser(response.user);
return response.user;
});
};
const signout = () => {
return Firebase
.auth()
.signOut()
.then(() => {
setUser(false);
});
};
const sendPasswordResetEmail = email => {
return Firebase
.auth()
.sendPasswordResetEmail(email)
.then(() => {
return true;
});
};
const confirmPasswordReset = (password, code) => {
// Get code from query string object
const resetCode = code || getFromQueryString("oobCode");
return Firebase
.auth()
.confirmPasswordReset(resetCode, password)
.then(() => {
return true;
});
};
// Subscribe to user on mount
useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged(user => {
if (user) {
setUser(user);
} else {
setUser(false);
}
});
// Subscription unsubscribe function
return () => unsubscribe();
}, []);
return {
user,
signup,
signin,
signout,
sendPasswordResetEmail,
confirmPasswordReset
};
}
const getFromQueryString = key => {
return queryString.parse(window.location.search)[key];
};
또한 다음과 같이 firebase 컨텍스트 제공자를 만들었습니다.
import React, { createContext } from 'react';
import Firebase from "../../firebase";
const FirebaseContext = createContext(null)
export { FirebaseContext }
export default ({ children }) => {
return (
<FirebaseContext.Provider value={ Firebase }>
{ children }
</FirebaseContext.Provider>
)
}
그런 다음 index.js에서 앱을 firebase 공급자로 래핑합니다.
ReactDom.render(
<FirebaseProvider>
<App />
</FirebaseProvider>,
document.getElementById("root"));
serviceWorker.unregister();
내 경로 목록에서 인증 공급자의 관련 경로를 래핑했습니다.
import React from "react";
import IndexPage from "./index";
import { Switch, Route, Router } from "./../util/router.js";
import { ProvideAuth } from "./../util/auth.js";
function App(props) {
return (
<ProvideAuth>
<Router>
<Switch>
<Route exact path="/" component={IndexPage} />
<Route
component={({ location }) => {
return (
<div
style={{
padding: "50px",
width: "100%",
textAlign: "center"
}}
>
The page <code>{location.pathname}</code> could not be found.
</div>
);
}}
/>
</Switch>
</Router>
</ProvideAuth>
);
}
export default App;
이 특정 시도에서 나는이 오류와 함께 이전에 플래그가 지정된 문제로 돌아갑니다.
TypeError : _firebase__WEBPACK_IMPORTED_MODULE_2 __. default.auth는 함수가 아닙니다
인증 제공자의이 행을 문제점 작성으로 지정하십시오.
useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged(user => {
if (user) {
setUser(user);
} else {
setUser(false);
}
});
Firebase에서 대문자 F를 사용하려고 시도했지만 동일한 오류가 발생합니다.
Tristan의 조언을 시도 할 때 모든 것을 제거하고 수신 거부 방법을 비공개 방법으로 정의하려고 시도합니다 (왜 그가 firebase 언어를 사용하지 않는지 모르겠지만 그의 접근 방식이 효과가 있다면 더 열심히 노력할 것입니다) 이유를 파악하기 위해). 그의 솔루션을 사용하려고하면 오류 메시지가 나타납니다.
TypeError : _util_contexts_Firebase__WEBPACK_IMPORTED_MODULE_8 ___ default (…)는 함수가 아닙니다
이 게시물에 대한 답변은 인증 후 ()를 제거 하도록 제안합니다. 시도하면 다음과 같은 오류가 발생합니다.
TypeError : 정의되지 않은 ‘onAuthStateChanged’속성을 읽을 수 없습니다
그러나이 게시물 은 auth 파일에서 firebase를 가져 오는 방식에 문제가 있음을 나타냅니다.
“../firebase”에서 import Firebase;
Firebase는 클래스 이름입니다.
Tristan이 권장하는 비디오는 유용한 배경이지만, 현재 에피소드 9에 있지만이 문제를 해결하는 데 도움이 될 부분을 찾지 못했습니다. 어디에서 찾을 수 있는지 아는 사람이 있습니까?
다음 공격
다음 – 컨텍스트 문제 만 해결하려고합니다-createContext와 useContext를 모두 가져 와서이 문서에 표시된대로 사용하려고했습니다.
다음과 같은 오류가 발생하지 않습니다.
오류 : 잘못된 후크 호출입니다. 후크는 함수 구성 요소의 본문 내부에서만 호출 할 수 있습니다. 다음과 같은 이유로 발생할 수 있습니다. …
나는 이 링크 의 제안을 겪어왔다 통해이 문제를 시도하고 해결했지만 이해할 수 없습니다. 이 문제 해결 가이드에 표시된 문제가 없습니다.
현재 상황 설명은 다음과 같습니다.
import React, { useContext } from 'react';
import Firebase from "../../firebase";
export const FirebaseContext = React.createContext();
export const useFirebase = useContext(FirebaseContext);
export const FirebaseProvider = props => (
<FirebaseContext.Provider value={new Firebase()}>
{props.children}
</FirebaseContext.Provider>
);
나는이 우디 코스 를 사용 하여 컨텍스트를 파악 하고이 문제에 대한 요소를 파악하려고 노력했습니다.이를 본 후 아래 Tristan이 제안한 솔루션의 유일한 측면은 createContext 메소드가 그의 게시물에서 올바르게 호출되지 않는다는 것입니다. “React.createContext”여야하지만 여전히 문제를 해결할 수있는 곳은 없습니다.
나는 아직도 붙어 있습니다.
여기서 무엇이 잘못되었는지 볼 수 있습니까?
답변
주요 편집 : 이것에 대해 좀 더 살펴보기 위해 시간을 들였습니다. 이것은 내가 찾은 것이 더 깨끗한 해결책입니다.
Firebase 인증 후크 사용
import { useEffect, useState, useCallback } from 'react';
import firebase from 'firebase/app';
import 'firebase/auth';
const firebaseConfig = {
apiKey: "xxxxxxxxxxxxxx",
authDomain: "xxxx.firebaseapp.com",
databaseURL: "https://xxxx.firebaseio.com",
projectId: "xxxx",
storageBucket: "xxxx.appspot.com",
messagingSenderId: "xxxxxxxx",
appId: "1:xxxxxxxxxx:web:xxxxxxxxx"
};
firebase.initializeApp(firebaseConfig)
const useFirebase = () => {
const [authUser, setAuthUser] = useState(firebase.auth().currentUser);
useEffect(() => {
const unsubscribe = firebase.auth()
.onAuthStateChanged((user) => setAuthUser(user))
return () => {
unsubscribe()
};
}, []);
const login = useCallback((email, password) => firebase.auth()
.signInWithEmailAndPassword(email, password), []);
const logout = useCallback(() => firebase.auth().signOut(), [])
return { login, authUser, logout }
}
export { useFirebase }
authUser가 널이면 인증되지 않고, 사용자에게 값이 있으면 인증됩니다.
firebaseConfig
firebase 콘솔 => 프로젝트 설정 => 앱 => 구성 라디오 버튼 에서 찾을 수 있습니다
useEffect(() => {
const unsubscribe = firebase.auth()
.onAuthStateChanged(setAuthUser)
return () => {
unsubscribe()
};
}, []);
이 useEffect 후크는 사용자의 인증 변경을 추적하는 핵심입니다. authUser의 값을 업데이트하는 fireAuth.auth ()의 onAuthStateChanged 이벤트에 리스너를 추가합니다. 이 메소드는 useFirebase 후크가 새로 고쳐질 때 리스너를 정리하는 데 사용할 수있는이 리스너를 구독 취소하기위한 콜백을 리턴합니다.
이것은 Firebase 인증에 필요한 유일한 후크입니다 (다른 후크는 Firestore 등을 위해 만들 수 있음).
const App = () => {
const { login, authUser, logout } = useFirebase();
if (authUser) {
return <div>
<label>User is Authenticated</label>
<button onClick={logout}>Logout</button>
</div>
}
const handleLogin = () => {
login("name@email.com", "password0");
}
return <div>
<label>User is not Authenticated</label>
<button onClick={handleLogin}>Log In</button>
</div>
}
이것은 App
구성 요소의 기본 구현입니다create-react-app
Firestore 데이터베이스 후크 사용
const useFirestore = () => {
const getDocument = (documentPath, onUpdate) => {
firebase.firestore()
.doc(documentPath)
.onSnapshot(onUpdate);
}
const saveDocument = (documentPath, document) => {
firebase.firestore()
.doc(documentPath)
.set(document);
}
const getCollection = (collectionPath, onUpdate) => {
firebase.firestore()
.collection(collectionPath)
.onSnapshot(onUpdate);
}
const saveCollection = (collectionPath, collection) => {
firebase.firestore()
.collection(collectionPath)
.set(collection)
}
return { getDocument, saveDocument, getCollection, saveCollection }
}
이것은 당신의 컴포넌트에서 다음과 같이 구현 될 수 있습니다 :
const firestore = useFirestore();
const [document, setDocument] = useState();
const handleGet = () => {
firestore.getDocument(
"Test/ItsWFgksrBvsDbx1ttTf",
(result) => setDocument(result.data())
);
}
const handleSave = () => {
firestore.saveDocument(
"Test/ItsWFgksrBvsDbx1ttTf",
{ ...document, newField: "Hi there" }
);
}
그러면 Firebase 자체에서 직접 업데이트를받을 때 React useContext가 필요하지 않습니다.
몇 가지 사항에 주목하십시오.
- 변경되지 않은 문서를 저장해도 새 스냅 샷이 트리거되지 않으므로 “과도하게 저장”해도 다시 렌더링되지 않습니다
- getDocument를 호출하면 초기 “스냅 샷”과 함께 onUpdate 콜백이 즉시 호출되므로 문서의 초기 상태를 얻는 데 추가 코드가 필요하지 않습니다.
편집은 이전 답변의 큰 덩어리를 제거했습니다
답변
Firebase는 가져 오지 않기 때문에 정의되지 않았습니다. 먼저 https://github.com/CSFrequency/react-firebase-hooks/tree/master/firestore에firebase.firestore()
연결된 문서의 예제에 표시된 것과 같아야합니다 . 그런 다음 firebase 패키지 readme https://www.npmjs.com/package/firebase에 설명 된대로 실제로 파일에서 firebase를 가져와야합니다.import * as firebase from 'firebase';
답변
편집 (2020 년 3 월 3 일) :
처음부터 시작합시다.
-
새 프로젝트를 만들었습니다.
털실은 반응 앱 파이어베이스 후크 문제를 만듭니다
-
기본적으로 생성 된 3 개의 App * 파일을 모두 삭제하고 index.js에서 가져 오기를 제거했으며 서비스 작업자를 제거하여 index.js를 깨끗하게 정리했습니다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const App = () => {
return (
<div>
Hello Firebase!
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
- Hello Firebase 를 확인하기 위해 앱을 시작했습니다 !인쇄됩니다.
- Firebase 모듈을 추가했습니다
yarn add firebase
- 해당 프로젝트의 firebase를 설정하기 위해 firebase init를 실행했습니다. 빈 firebase 프로젝트 중 하나를 선택했으며 다음 파일을 생성하는 데이터베이스 및 Firestore를 선택했습니다.
.firebaserc
database.rules.json
firebase.json
firestore.indexes.json
firestore.rules
- firebase 라이브러리에 대한 가져 오기를 추가하고 Firebase 클래스 및 FirebaseContext 도 만들었습니다 . 마지막으로 FirebaseContext.Provider 구성 요소 에서 앱을 래핑 하고 값을 새 Firebase () 인스턴스로 설정했습니다. 단일 인스턴스 여야하므로 Firebase 앱 인스턴스를 하나만 인스턴스화해야했습니다.
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import app from "firebase/app";
import "firebase/database";
import "firebase/auth";
import "firebase/firestore";
class Firebase {
constructor() {
app.initializeApp(firebaseConfig);
this.realtimedb = app.database();
this.firestore = app.firestore();
}
}
const FirebaseContext = React.createContext(null);
const firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
};
const App = () => {
return <div>Hello Firebase!</div>;
};
ReactDOM.render(
<FirebaseContext.Provider value={new Firebase()}>
<App />
</FirebaseContext.Provider>
, document.getElementById("root"));
-
Firestore에서 무엇이든 읽을 수 있는지 확인합시다. 첫번째 단지 읽기를 확인하기 위해, 나는 중포 기지 콘솔에서 내 프로젝트라는 새 컬렉션 내 클라우드 경우 FireStore 데이터베이스를 열고 추가에 갔다 카운터 문서와 간단한 라는 하나 개의 필드에 포함 된 값 유형 번호와 값 0을.
-
그런 다음 생성 한 FirebaseContext를 사용하도록 App 클래스를 업데이트하고 간단한 카운터 후크에 useState 후크를 만들고 useEffect 후크를 사용하여 firestore에서 값을 읽었습니다.
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import app from "firebase/app";
import "firebase/database";
import "firebase/auth";
import "firebase/firestore";
const firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
};
class Firebase {
constructor() {
app.initializeApp(firebaseConfig);
this.realtimedb = app.database();
this.firestore = app.firestore();
}
}
const FirebaseContext = React.createContext(null);
const App = () => {
const firebase = React.useContext(FirebaseContext);
const [counter, setCounter] = React.useState(-1);
React.useEffect(() => {
firebase.firestore.collection("counters").doc("simple").get().then(doc => {
if(doc.exists) {
const data = doc.data();
setCounter(data.value);
} else {
console.log("No such document");
}
}).catch(e => console.error(e));
}, []);
return <div>Current counter value: {counter}</div>;
};
ReactDOM.render(
<FirebaseContext.Provider value={new Firebase()}>
<App />
</FirebaseContext.Provider>
, document.getElementById("root"));
참고 : 답변을 최대한 짧게 유지하려면 firestore에 대한 액세스를 테스트 모드 (firestore.rules 파일)로 설정하여 firebase로 인증 할 필요가 없도록했습니다.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// This rule allows anyone on the internet to view, edit, and delete
// all data in your Firestore database. It is useful for getting
// started, but it is configured to expire after 30 days because it
// leaves your app open to attackers. At that time, all client
// requests to your Firestore database will be denied.
//
// Make sure to write security rules for your app before that time, or else
// your app will lose access to your Firestore database
match /{document=**} {
allow read, write: if request.time < timestamp.date(2020, 4, 8);
}
}
}
내 이전 답변 :
당신은 내 react-firebase-auth-skeleton을 살펴 보는 것을 환영합니다.
https://github.com/PompolutZ/react-firebase-auth-skeleton
주로 기사를 따릅니다.
https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial
그러나 후크를 사용하도록 다소 다시 작성되었습니다. 나는 적어도 두 개의 프로젝트에서 그것을 사용했다.
현재 애완 동물 프로젝트의 일반적인 사용법 :
import React, { useState, useEffect, useContext } from "react";
import ButtonBase from "@material-ui/core/ButtonBase";
import Typography from "@material-ui/core/Typography";
import DeleteIcon from "@material-ui/icons/Delete";
import { FirebaseContext } from "../../../firebase";
import { useAuthUser } from "../../../components/Session";
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
position: "relative",
"&::-webkit-scrollbar-thumb": {
width: "10px",
height: "10px",
},
},
itemsContainer: {
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
display: "flex",
alignItems: "center",
overflow: "auto",
},
}));
export default function LethalHexesPile({
roomId,
tokens,
onSelectedTokenChange,
}) {
const classes = useStyles();
const myself = useAuthUser();
const firebase = useContext(FirebaseContext);
const pointyTokenBaseWidth = 95;
const [selectedToken, setSelectedToken] = useState(null);
const handleTokenClick = token => () => {
setSelectedToken(token);
onSelectedTokenChange(token);
};
useEffect(() => {
console.log("LethalHexesPile.OnUpdated", selectedToken);
}, [selectedToken]);
const handleRemoveFromBoard = token => e => {
console.log("Request remove token", token);
e.preventDefault();
firebase.updateBoardProperty(roomId, `board.tokens.${token.id}`, {
...token,
isOnBoard: false,
left: 0,
top: 0,
onBoard: { x: -1, y: -1 },
});
firebase.addGenericMessage2(roomId, {
author: "Katophrane",
type: "INFO",
subtype: "PLACEMENT",
value: `${myself.username} removed lethal hex token from the board.`,
});
};
return (
<div className={classes.root}>
<div className={classes.itemsContainer}>
{tokens.map(token => (
<div
key={token.id}
style={{
marginRight: "1rem",
paddingTop: "1rem",
paddingLeft: "1rem",
filter:
selectedToken &&
selectedToken.id === token.id
? "drop-shadow(0 0 10px magenta)"
: "",
transition: "all .175s ease-out",
}}
onClick={handleTokenClick(token)}
>
<div
style={{
width: pointyTokenBaseWidth * 0.7,
position: "relative",
}}
>
<img
src={`/assets/tokens/lethal.png`}
style={{ width: "100%" }}
/>
{selectedToken && selectedToken.id === token.id && (
<ButtonBase
style={{
position: "absolute",
bottom: "0%",
right: "0%",
backgroundColor: "red",
color: "white",
width: "2rem",
height: "2rem",
borderRadius: "1.5rem",
boxSizing: "border-box",
border: "2px solid white",
}}
onClick={handleRemoveFromBoard(token)}
>
<DeleteIcon
style={{
width: "1rem",
height: "1rem",
}}
/>
</ButtonBase>
)}
</div>
<Typography>{`${token.id}`}</Typography>
</div>
))}
</div>
</div>
);
}
가장 중요한 두 부분은 다음과 같습니다.- 현재 인증 된 사용자를 제공하는 useAuthUser () 후크. -useContext 후크 를 통해 사용하는 FirebaseContext .
const firebase = useContext(FirebaseContext);
firebase에 대한 컨텍스트가 있으면 원하는대로 firebase 객체를 구현해야합니다. 때로는 유용한 기능을 작성하고 때로는 현재 구성 요소에 대해 사용 하는 useEffect 후크 에서 리스너를 설정하기가 더 쉽습니다 .
이 기사의 가장 좋은 부분 중 하나는 withAuthorization HOC를 작성하는 것인데 ,이를 통해 컴포넌트 자체에서 페이지에 액세스하기위한 전제 조건을 지정할 수 있습니다.
const condition = authUser => authUser && !!authUser.roles[ROLES.ADMIN];
export default withAuthorization(condition)(AdminPage);
또는 라우터 구현에서 바로 이러한 조건을 설정할 수도 있습니다.
리포지토리와 기사를 보면 질문에 대한 다른 훌륭한 답변을 향상시킬 수있는 좋은 생각을 얻을 수 있기를 바랍니다.