I am trying to use redux to store user's login information. When he logs in, the application has to store his name and login date/time. I will present the code then I will describe the problem.
App.tsx
import { Redirect, Route } from 'react-router-dom';
import { IonApp, IonRouterOutlet, IonSpinner } from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import Home from './pages/Home';
import Login from './pages/Login';
import Register from './pages/Register';
import { useEffect, useState } from 'react';
import { getCurrentUser } from './pages/FirebaseServices'
import Dashboard from './pages/Dashboard';
import { useDispatch } from 'react-redux';
import { setUserDate, setUserState } from './reducers/actions';
const RoutingSystem: React.FC = () => {
return (
<IonReactRouter>
<IonRouterOutlet>
<Route exact path="/home">
<Home />
</Route>
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route exact path="/dashboard" component={Dashboard} />
<Route exact path="/">
<Redirect to="/home" />
</Route>
</IonRouterOutlet>
</IonReactRouter>
)
}
const App: React.FC = () => {
const [busy, setBusy] = useState<boolean>(true)
const dispatch = useDispatch()
useEffect(() => {
getCurrentUser().then((user: any) => {
if (user) {
//dispatch(setUserState(user.email))
//dispatch(setUserDate(Date().toLocaleString()))
window.history.replaceState({}, '', '/dashboard')
} else {
window.history.replaceState({}, '', '/')
}
setBusy(false)
})
}, [dispatch])
return <IonApp> {busy ? <IonSpinner /> : <RoutingSystem />} </IonApp>
}
export default App;
FirebaseServices.tsx
import { resolve } from 'node:url'
import { auth } from '..'
import { toast } from './Toast'
export async function loginUser(username: string, password: string) {
const email = `${username}@app.com`
try {
const res = await auth.signInWithEmailAndPassword(email, password)
return {type: true, email: res.user?.email}
} catch (error) {
console.log(error.message)
toast(error.message, 10000)
return {type: false, email: ''}
}
}
Login.tsx
import { IonBackButton, IonButton, IonButtons, IonContent, IonHeader, IonInput, IonLoading, IonPage, IonTitle, IonToolbar } from "@ionic/react"
import React, { useState } from "react"
import { useDispatch } from "react-redux"
import { Link } from "react-router-dom"
import { setUserDate, setUserState } from "../reducers/actions"
import { loginUser } from "./FirebaseServices"
import { toast } from "./Toast"
const Login: React.FC = () => {
const [busy, setBusy] = useState<boolean>(false)
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const dispatch = useDispatch()
async function login() {
setBusy(true)
console.log(username, password)
const res : any = await loginUser(username,password)
if(res.type){
dispatch(setUserState(res.email))
dispatch(setUserDate(Date().toLocaleString()))
toast("Você logou com sucesso")
}
setBusy(false)
}
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonBackButton defaultHref="/home" />
</IonButtons>
<IonTitle slot="end">
Login
</IonTitle>
</IonToolbar>
</IonHeader>
<IonLoading message="Aguarde..." isOpen={busy} duration={0} />
<IonContent className="ion-padding">
<IonInput placeholder="Digite o nome do usuário" onIonChange={e => setUsername(e.detail.value!)} />
<IonInput type="password" placeholder="Digite a senha" onIonChange={e => setPassword(e.detail.value!)} />
<IonButton color="primary" onClick={login}> Login</IonButton>
<p>
Novo por aqui? <Link to="./register"> Registrar</Link>
</p>
</IonContent>
</IonPage>
)
}
export default Login
Dashboard.tsx
import { IonBackButton, IonButton, IonButtons, IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from "@ionic/react"
import React from "react"
import { signOff } from "./FirebaseServices"
import { auth } from '..'
import { useSelector } from "react-redux"
const Dashboard: React.FC = () => {
const username = useSelector((state: any) => state.user.username)
const date = useSelector((state: any) => state.time.lastLogin)
async function off() {
signOff()
}
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonBackButton defaultHref="/home" />
</IonButtons>
<IonTitle slot="end">
Dashboard
</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding">
<p> Nome do usuário no Redux Store {username}</p>
<br></br>
<p>Data: {date} </p>
<IonButton color="primary" onClick={off}> Sign out</IonButton>
</IonContent>
</IonPage>
)
}
export default Dashboard
index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
import reportWebVitals from './reportWebVitals';
import firebase from 'firebase/app'
import 'firebase/auth'
import { Provider } from 'react-redux';
import reducer from "./reducers/reducers"
import { createStore } from 'redux';
firebase.initializeApp({
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: ""
});
export const auth = firebase.auth();
const store = createStore(reducer)
ReactDOM.render(
<Provider store={store}>
<React.StrictMode>
<App />
</React.StrictMode>
</Provider>,
document.getElementById('root')
);
serviceWorkerRegistration.unregister();
reportWebVitals();
actions.tsx
export const setUserState = (payload: any) => {
return { type: 'SET_USER_STATE', payload}
}
export const setUserDate = (payload: string) => {
return {type: 'SET_USER_DATE', payload}
}
reducers.tsx
const defaultState = {
user: {},
time: {}
}
export default function reducer(state = defaultState,
{ type, payload }: { type: string; payload: any }): any {
switch (type) {
case 'SET_USER_STATE':
return {
...state,
user: {
username: payload.split('@')[0],
}
}
case 'SET_USER_DATE':
return {
...state,
time: {
lastLogin: payload
}
}
default:
return state
}
}
Problem
I have success using useDispatch() inside the useEffect(). However, when I try to use it inside the Login component (Login.tsx), it didn't work. What is going on?
I am reading about redux, but I can't figure out what I am missing here.