I am using Router and customHistory to help me redirect the pages, but the pages not render correctly.
The code works like this: if the user is authorized or log in, then the user should be redirected to "localhost:8080/dashboard" and see the dashboard(with data fetching from firebase) & header; if the use is log out, then the user should be redirect to "locahost:8080/" and see the log in button with the header.
However, after I successfully log in, the url is "localhost:8080/dashboard" without any data fetched from firebase, only things I can see are the header and login button. But if I hit "RETURN" with the current url which is "localhost:8080/dashboard", it will redirect to correct page with all data fetching from firebase, and no login button.
This is the github_link to the code. I have spent times searching online, but do not find any positive result except this one. After reading the stackoverflow I feel my code has some problems with asynchronization. Any thoughts?
I really appreciate for your help! Thanks!
This is my AppRouter.js:
export const customHistory = createBrowserHistory();
const AppRouter = () => (
<Router history={customHistory}>
<div>
<Header />
<Switch>
<Route path="/" exact component={LoginPage} />
<Route path="/dashboard" component={ExpenseDashboardPage} />
<Route path="/create" component={AddExpensePage} />
<Route path="/edit/:id" component={EditExpensePage} />
<Route path="/help" component={HelpPage} />
<Route component={LoginPage} />
</Switch>
</div>
</Router>
);
This is my app.js
import React, { Children } from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import "normalize.css/normalize.css"; //Normalize.css makes browsers render all elements more consistently and in line with modern standards.
import "./styles/styles.scss";
import AppRouter, { customHistory } from "./routers/AppRouter";
import configureStore from "./redux/store/configStore";
import { startSetExpenses } from "./redux/actions/expenses";
import { login, logout } from "./redux/actions/auth";
import "react-dates/lib/css/_datepicker.css";
import { firebase } from "./firebase/firebase";
//for testing: npm test -- --watch
const store = configureStore();
const jsx = (
<Provider store={store}>
<AppRouter />
</Provider>
);
ReactDOM.render(<p>Loading...</p>, document.getElementById("app"));
let hasRendered = false;
const renderApp = () => {
if (!hasRendered) {
ReactDOM.render(jsx, document.getElementById("app"));
hasRendered = true;
}
};
firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log("log in");
store.dispatch(login(user.uid));
store.dispatch(startSetExpenses()).then(() => {
renderApp();
if (customHistory.location.pathname === "/") {
customHistory.push("/dashboard");
}
});
} else {
console.log("log out");
store.dispatch(logout());
renderApp();
customHistory.push("/");
}
});
This is the header.js
import React from "react";
import { BrowserRouter, Route, Switch, Link, NavLink } from "react-router-dom";
import { connect } from "react-redux";
import { startLogout } from "../redux/actions/auth";
export const Header = ({ startLogout }) => (
<header>
<h1>Expensify</h1>
<NavLink to="/" activeClassName="is-active">
Dashboard
</NavLink>
<NavLink to="/create" activeClassName="is-active">
CreateExpense
</NavLink>
<button onClick={startLogout}>Logout</button>
</header>
);
const mapDispatchToProps = (dispatch) => ({
startLogout: () => dispatch(startLogout()),
});
export default connect(undefined, mapDispatchToProps)(Header);