首页 > 解决方案 > 如何确保我有来自上下文提供程序的用户数据,或者在我加载页面之前用户已登录?

问题描述

在我的反应应用程序中正确保护路线时遇到了一些麻烦。看看其他例子,很多人都在使用 react 组件而不是钩子,我的应用程序是由钩子组成的。

我使用 firebase 作为我的身份验证方法。

auth用来检查电子邮件、密码、登录等,并有一个名为的对象userData存储姓名、用户名、地址、简历等。

这是我的 React App.js:

function App() {
  const [{}, dispatch] = useStateValue();
  const [userData, setUserData] = useState("");

  const getUserData = () => {
    var userData = db.collection("users").doc(auth.currentUser.uid);
    userData
      .get()
      .then((doc) => {
        if (doc.exists) {
          console.log("Document data:", doc.data());
          setUserData(doc.data());
        } else {
          // doc.data() will be undefined in this case
          console.log("No such document!");
        }
      })
      .catch((error) => {
        console.log("Error getting document:", error);
      });
  };

  useEffect(() => {
    if (userData) {
      dispatch({
        type: "SET_USERDATA",
        userData: userData,
      });
    }
  }, [userData]);

  useEffect(() => {
    auth.onAuthStateChanged((authUser) => {
      if (authUser) {
        getUserData();
        dispatch({
          type: "SET_USER",
          user: authUser,
        });
      } else {
        //else the user is logged out
        dispatch({
          type: "SET_USER",
          user: null,
        });
      }
    });
  }, []);

  return (
    <Router>
      <div className="App">
        <Switch>
          <Route path="/signup">
            <Signup />
          </Route>
          <Route path="/login">
            <Login />
          </Route>
          <Route path="/edit">
            <Header />
            <EditProfile />
          </Route>
          <Route path="/checkout">
            <Header />
            <Checkout />
          </Route>
          <Route path="/l/:listingID">
            <Header />
            <ListingPage />
          </Route>
          <Route path="/e/:listingID">
            <Header />
            <EditListing />
          </Route>
          <Route path="/p/:userProfile">
            <Header />
            <Profile />
          </Route>
          <Route path="/sendTradeOffer/:tradePartnerID">
            <Header />
            <SendTradeOffer />
          </Route>
          <Route path="/list">
            <Header />
            <ListItem />
          </Route>
          <Route path="/help">
            <Header />
            <Help />
          </Route>
          <Route path="/s/:searchQuery">
            <Header />
            <Search />
          </Route>
          <Route path="/messages">
            <Header />
            <Messages />
          </Route>
          <Route path="/trade/:tradeID">
            <Header />
            <TradeInstance />
          </Route>
          <Route path="/payment/:listingID">
            <Elements stripe={promise}>
              <Payment />
            </Elements>
          </Route>
          <Route path="/checkoutSuccess">
            <CheckoutSuccess />
          </Route>
          <Route exact path="/">
            <Header />
            <Home />
          </Route>
          <Route>
            <Header />
            <Error />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

export default App;

正如您在上面看到的,是auth状态变化,我将auth对象分派到我的 reducer.js 中,然后调用getUserData()以获取额外的数据,然后分派它。

但是,我遇到的一个问题是例如“编辑个人资料”。

当您单击编辑配置文件并且您没有登录时,您会被重定向到登录页面,这很棒!但是,如果您输入 localhost:3000/edit,它仍然会呈现没有任何信息的页面。

另外,有时当我加载某些页面时,我需要获取 userData,所以我使用:

const [{ userData }] = useStateValue();

然而,很多时候会null在一瞬间返回,导致我的应用程序有时会崩溃。

基本上,我在保持我的应用程序同步时遇到了很多问题,确保它只向登录用户呈现某些内容,并且还等待通过我的上下文提供程序传递 userData

任何人都可以推动我朝着正确的方向前进吗?

标签: reactjsfirebasegoogle-cloud-firestorefirebase-authenticationstate

解决方案


推荐阅读