C:\Users\Administrator\Desktop\start\src\middlewares\thunks.tsx
import { loginApi } from './../apis/user';
import * as actions from './../actions';
import * as interfaces from './../interface';
import { Dispatch } from 'redux';
export const login = (payload: interfaces.ReqLogin) => (dispatch:Dispatch) => {
dispatch(actions.loginRequested());
return loginApi(payload)
.then(res => {
localStorage.setItem('token', res.data.access_token)
return dispatch(actions.loginSuccess(res))
})
.catch(err => Promise.reject(dispatch(actions.loginFailed(err))))
}
C:\Users\Administrator\Desktop\start\tsconfig.json
Thêm "noImplicitAny": false vào compilerOptions để nó không đòi hoi kiểu dữ liệu
C:\Users\Administrator\Desktop\start\src\pages\Login\index.tsx
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { PATH } from './../../constants/paths';
import { login } from './../../middlewares/thunks';
function Login(props: any) {
const { login, loading } = props;
const history = useHistory();
const [username, setUsername] = useState('admin');
const [password, setPassword] = useState('123');
const [error, setError] = useState('');
const submit = async (event: React.FormEvent < HTMLFormElement > ) => {
event.preventDefault();
const payload = { username, password };
login(payload)
.then(res => {
history.push({ pathname: PATH.HOME })
})
.catch(err => {
setError(err.payload.message)
})
}
return (
<div className="container">
<form id="login" className="border p-2 rounded" onSubmit={submit}>
<h2 className="text-center text-primary">Login</h2>
<p className="text-center text-secondary">Lorem ipsum dolor sit amet.</p>
<div className="form-group">
<input type="text" placeholder="Username" className="form-control" />
</div>
<div className="form-group">
<input type="password" placeholder="Password" className="form-control" />
</div>
<div className="form-group text-center">
<button type="submit" className="btn btn-primary btn-md">Login</button>
</div>
</form>
</div>
)
}
const mapStateToProps = (state: any) => ({
loading: false
});
const mapDispatchToProps = {
login
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
C:\Users\Administrator\Desktop\start\src\actions\index.tsx
import * as types from './../constants/login';
export const loginRequested = ():any => ({
type: types.LOGIN_REQUESTED
})
export const loginSuccess = (payload:any) => ({
type: types.LOGIN_SUCCESS,
payload
})
export const loginFailed = (payload:any) => ({
type: types.LOGIN_FAILED,
payload
})
C:\Users\Administrator\Desktop\start\src\apis\user.tsx
import * as interfaces from './../interface';
export const loginApi = ({ username, password }: interfaces.ReqLogin): Promise < interfaces.ResLoginApi > =>
new Promise((resolve, reject) => {
setTimeout(() => {
if (username === 'admin' && password === '123') {
resolve({
data: {
access_token: '82jdu82193yh90sad83hxfgsd'
},
message: 'Login thành công'
})
} else {
reject(new Error('Login thất bại'))
}
}, 100)
});
C:\Users\Administrator\Desktop\start\src\interface\index.tsx
import { RouteProps, RouteComponentProps } from 'react-router-dom';
export interface ReduxProps {
isAuthenticated: boolean
}
export interface Props extends ReduxProps, RouteProps {
component: React.ComponentType < RouteComponentProps >
}
export interface ReqLogin {
username: string
password: string
}
export interface Res {
data: any
message: string
}
export interface ResLoginApi extends Res {
data: {
access_token: string
}
}
export interface ActionRedux {
type: any
payload ?: any
}
C:\Users\Administrator\Desktop\start\src\constants\login.tsx
export const LOGIN_REQUESTED = 'views/login/LOGIN_REQUESTED';
export const LOGIN_SUCCESS = 'views/login/LOGIN_SUCCESS';
export const LOGIN_FAILED = 'views/login/LOGIN_FAILED';
export const LOGOUT = 'app/LOGOUT';