7. Tạo reducer productList, productList 1 (ok)
C:\Users\Administrator\Desktop\typescript\src\routes\index.tsx
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import HomeRoutes from './HomeRoutes';
import ProductRoutes from './ProductRoutes';
import LoginRoutes from './LoginRoutes';
function Routes() {
return (
<Router>
<HomeRoutes />
<LoginRoutes />
<ProductRoutes />
</Router>
)
}
export default Routes;
C:\Users\Administrator\Desktop\typescript\src\reducer\products.tsx
import * as products from './../constants/products';
import produce from 'immer';
import * as interfaces from './../interface';
const initialState = {
loading: false,
productList: [] as interfaces.Product[]
}
export const ProductListReducer = (state = initialState, action) =>
produce(state, draft => {
switch (action.type) {
case products.GET_PRODUCT_LIST_REQUESTED:
draft.loading = true
break
case products.GET_PRODUCT_LIST_SUCCESS:
draft.loading = false
draft.productList = action.payload.data.products
break
case products.GET_PRODUCT_LIST_FAILED:
draft.loading = false
break
default:
return state
}
})
C:\Users\Administrator\Desktop\typescript\src\pages\Product\ProductList\index.tsx
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import MainLayout from './../../../layouts/MainLayout';
import { TableContainer } from './ProductList.styles';
import { getProductList } from './../../../middlewares/thunks';
import * as interfaces from './../../../interface';
interface ReduxProps {
productList: interfaces.Product[]
getProductList(): Promise<interfaces.ResGetProduct>
}
interface Props extends ReduxProps {}
const ProductList = (props: Props) => {
const { getProductList, productList } = props;
useEffect(() => {
getProductList()
}, [getProductList])
return (
<MainLayout>
<h2>Product List</h2>
<TableContainer>
<table className="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Quantity</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td>Iphone</td>
<td>100</td>
<td>27,000,000 đ</td>
<td><a className="btn btn-primary" href="/product/1">Detail</a></td>
</tr>
<tr>
<th>2</th>
<td>Samsung</td>
<td>28</td>
<td>22,000,000 đ</td>
<td><a className="btn btn-primary" href="/product/2">Detail</a></td>
</tr>
<tr>
<th>3</th>
<td>Nokia</td>
<td>10</td>
<td>15,000,000 đ</td>
<td><a className="btn btn-primary" href="/product/3">Detail</a></td>
</tr>
<tr>
<th>4</th>
<td>Sony</td>
<td>44</td>
<td>25,000,000 đ</td>
<td><a className="btn btn-primary" href="/product/4">Detail</a></td>
</tr>
</tbody>
</table>
</TableContainer>
</MainLayout>
)
}
const mapStateToProps = state => ({
productList: state.productList.productList
})
const mapDispatchToProps = {
getProductList
}
export default connect(mapStateToProps, mapDispatchToProps)(ProductList);
C:\Users\Administrator\Desktop\typescript\src\interface\index.tsx
import React, {ReactNode} from 'react';
import { RouteProps, RouteComponentProps } from 'react-router-dom';
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 ReduxProps {
isAuthenticated: boolean
}
export interface Props extends ReduxProps, RouteProps {
component: React.ComponentType < RouteComponentProps >
}
export interface ActionRedux {
type: any
payload?: any
}
export interface ResLogin extends ActionRedux {
}
export interface PropsNodes {
children: ReactNode
}
export interface Product {
id: string
name: string
quantity: number
price: number
}
export interface ResGetProductApi extends Res {
data: {
products: Product[]
}
}
export interface ResGetProduct extends ActionRedux {
payload: ResGetProductApi
}
export interface ResGetProductItemApi extends Res {
data: {
product: Product
}
}
export interface ResGetProductItem extends ActionRedux {
payload: ResGetProductItemApi
}
C:\Users\Administrator\Desktop\typescript\src\reducer\index.tsx
import { combineReducers } from 'redux';
import { AppReducer } from './app';
import { loginReducer } from './login';
import { ProductListReducer } from './products';
const rootReducer = combineReducers({
app: AppReducer,
login: loginReducer,
productList: ProductListReducer
})
export default rootReducer;
C:\Users\Administrator\Desktop\typescript\src\middlewares\thunks.tsx
import { loginApi } from './../apis/user';
import { getProductListApi } from './../apis/product';
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))))
}
export const getProductList = () => dispatch => {
dispatch(actions.getProductListRequested())
return getProductListApi()
.then(res => dispatch(actions.getProductListSuccess(res)))
.catch(err => Promise.reject(dispatch(actions.getProductListFailed(err))))
}
C:\Users\Administrator\Desktop\typescript\src\actions\index.tsx
import * as types from './../constants/login';
import * as products from './../constants/products';
import * as interfaces from './../interface';
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
})
export const logout = () => ({
type: types.LOGOUT
})
export const getProductListRequested = () => ({
type: products.GET_PRODUCT_LIST_REQUESTED
})
export const getProductListSuccess = payload => {
return {
type: products.GET_PRODUCT_LIST_SUCCESS,
payload
}
}
export const getProductListFailed = payload => ({
type: products.GET_PRODUCT_LIST_FAILED,
payload
})
C:\Users\Administrator\Desktop\typescript\src\constants\products.tsx
export const GET_PRODUCT_LIST_REQUESTED = 'views/ProductList/GET_PRODUCT_LIST_REQUESTED';
export const GET_PRODUCT_LIST_SUCCESS = 'views/ProductList/GET_PRODUCT_LIST_SUCCESS';
export const GET_PRODUCT_LIST_FAILED = 'views/ProductList/GET_PRODUCT_LIST_FAILED';
C:\Users\Administrator\Desktop\typescript\src\apis\product.tsx
import * as interfaces from './../interface';
const mockProducts = [
{
id: '1',
name: 'Iphone',
quantity: 100,
price: 27000000
},
{
id: '2',
name: 'Samsung',
quantity: 28,
price: 22000000
},
{
id: '3',
name: 'Nokia',
quantity: 10,
price: 15000000
},
{
id: '4',
name: 'Sony',
quantity: 44,
price: 25000000
}
]
export const getProductListApi = (): Promise<interfaces.ResGetProductApi> =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
data: {
products: mockProducts
},
message: 'Lấy sản phẩm thành công'
})
}, 100)
})
export const getProductItemApi = (id: string): Promise<interfaces.ResGetProductItemApi> =>
new Promise((resolve, reject) => {
setTimeout(() => {
const product = mockProducts.find(product => product.id === id)
if (product) {
resolve({
data: {
product
},
message: 'Lấy sản phẩm thành công'
})
} else {
reject(new Error('Không tìm thấy sản phẩm'))
}
}, 100)
})
Last updated
Was this helpful?