【发布时间】:2021-07-04 09:02:17
【问题描述】:
大家好 - 我正在使用 Next.js 和 Firebase 构建一个应用程序,这两种技术对我来说都是全新的。这是一个简单的应用程序,用户创建一个帐户并且必须登录。如果用户不创建一个帐户,该应用程序将毫无用处——他们无法进入下一个屏幕,即仪表板。无论如何,当他们登录时,他们就可以创建旅行/度假行程。我将 Firebase Auth 用于身份验证,并将 Firestore(不是实时数据库)用作我的数据库。我的目标是,当用户登录时,用户可以看到他们创建的每个行程,而没有其他人的。它应该是完整的 CRUD。这也是我第一次进行这种身份验证,所以这可能会增加我的困惑。
我知道我的代码不正确,但它确实有效。不断发生的是,用户登录和注销时似乎存在延迟。我已经在本地副本上对此进行了测试。当我注销然后以其他用户身份重新登录时,它告诉我 uid 为空。 1 到 30 分钟后(严重),页面突然加载了我登录时使用的 uid!我读过的所有内容都表明身份验证存在延迟,但除了指出问题之外,我真的找不到解决方案——所以基本上写了一个控制台日志,说明当时谁登录了,然后同样当他们注销时。另外,我观看/阅读了大量教程,所以也许这是我的代码?对于这部代码小说,我提前感到非常抱歉——我会尽我所能组织起来!
这是我的配置信息,所以我将 Firebase 称为火。登录方法是电子邮件和密码,就在身份验证屏幕上捕获该信息而言,一切在 Firebase 中看起来都应该如此。
import firebase from 'firebase';
const firebaseConfig = {
apiKey: 'AIzaSyB-xEPETXSfjboKe5H0kPUu-ZdRDGfszmA',
authDomain: "where-to-jess.firebaseapp.com",
databaseURL: 'https://where-to-jess-default-rtdb.firebaseio.com/',
projectId: "where-to-jess",
storageBucket: "where-to-jess.appspot.com",
messagingSenderId: "914509599583",
appId: "1:914509599583:web:80cdf3e4090417b0f35cea"
};
try {
firebase.initializeApp(firebaseConfig);
} catch(err){
if (!/already exists/.test(err.message)) {
console.error('Firebase initialization error', err.stack)}
}
const fire = firebase;
export default fire;
当用户创建帐户时,他们也会被添加到我的数据库中的集合“用户”中。我也在使用 React Hooks(第一次)。他们的电子邮件是他们登录的用户名,但我正在数据库中捕获他们的电子邮件。他们也会在创建帐户后立即登录。这部分也有效。
const handleSubmit = (e) => {
e.preventDefault();
setPassword('');
fire.auth().createUserWithEmailAndPassword(userName, password)
.then(() => {
fire.firestore().collection('users').doc(fire.auth().currentUser.uid)
.set({
firstName: firstName,
lastName: lastName,
email: userName
})
.catch(error => {
console.log('user wasn\'t added to db: ', error);
})
})
.catch(error => {
console.log('user wasn\'t able to create an account: ', error);
})
router.push('/users/dashboard')
};
这是我的登录代码:
const handleLogin = (e) => {
e.preventDefault();
fire.auth()
.signInWithEmailAndPassword(username, password)
.catch((error) => {
console.log('user wasn\'t able to login: ', error);
})
setUsername('')
setPassword('')
router.push('/users/dashboard')
};
现在是有趣的部分!这是我的行程表单提交代码。我在这里想要实现的是将这个新创建的行程附加到他们在“用户”数据库中的 uid。我省略了所有表单内容,因为它超长。这似乎也有效——无论我使用哪个帐户,我都可以在数据库中看到它。
const handleSubmit = (e) => {
e.preventDefault();
fire.firestore()
.collection('users').doc(fire.auth().currentUser.uid).collection('itineraries')
.add({
//
})
.catch(error => {
console.log('itinerary not added to db ', error)
})
router.push('/users/dashboard')
}
这就是它发生的地方!我怀疑这是因为我在偷工减料,我将在下面解释。此仪表板应仅显示当前登录用户创建的行程。如果当前登录的用户没有创建任何行程,我会收到一个错误,说 uid 为空。所以,我的解决方法是在他们帐户的数据库中手动创建一个假行程(因为我正在测试)并将 tripName 值设为空。这似乎可行,但这就是奇怪的登录/注销事情发生的地方。
export default function Dashboard() {
const router = useRouter();
const [itineraries, setItineraries] = useState([]);
const [loggedIn, setLoggedIn] = useState(false);
fire.auth()
.onAuthStateChanged((user) => {
if (user) {
console.log(user.email + " is logged in!");
setLoggedIn(true)
} else {
setLoggedIn(false)
console.log('User is logged out!');
}
})
useEffect(() => {
const unsubscribe =
fire.firestore()
.collection('users').doc(fire.auth().currentUser.uid).collection('itineraries').where('tripName', '!=', 'null')
.onSnapshot(snap => {
const itineraries = snap.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
setItineraries(itineraries);
return () => {
unsubscribe();
};
});
}, []);
const handleLogout = () => {
fire.auth()
.signOut()
router.push('/')
};
最后,这是我在 db 上的一条规则。我在阅读规则文档时感到困惑,我觉得我在这里偷工减料。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read
allow write
}
}
}
再次,我真的很抱歉所有这些代码。这是我第一次使用 React Hooks、Next 和 Firebase——所以它是 Firebases 的文档、教程和我自己的代码的混搭。如有任何帮助或建议,我将不胜感激。
【问题讨论】:
标签: reactjs firebase google-cloud-firestore firebase-authentication firebase-security