Commit ae47cfa4 authored by mayi's avatar mayi
Browse files

study完成,axjx异步获取数据,MVC-Redux转变,中间件redux-thunk使用来处理异步action

parent c90e538d
This diff is collapsed.
......@@ -6,10 +6,11 @@ import "./i18n/configs";
import "antd/dist/antd.css";
import { Provider } from "react-redux";
import store from "./redux/store";
import axios from 'axios'
axios.defaults.headers['x-icode'] = '0D1F49DD13B9C757';
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
......
import * as React from "react";
// import { Component } from "react";
import {withTranslation,WithTranslation} from 'react-i18next'
import { withTranslation, WithTranslation } from "react-i18next";
import {
Header,
Footer,
......@@ -9,20 +10,79 @@ import {
ProductCollection,
Bussiness,
} from "../../components";
import { connect } from "react-redux";
import styles from "./home.module.css";
import {
// fetchRecommendProductSuccessActionCreator,
// fetchRecommendProductStartActionCreator,
// fetchRecommendProductFailActionCreator,
giveMeDataActionCreator
} from "../../redux/recommendProducts/recommendProductActions";
//0D1F49DD13B9C757
import { productList1, productList2, productList3 } from "./mockups";
import sideImage1 from "../../assets/images/sider_2019_02-04-2.png";
import sideImage2 from "../../assets/images/sider_2019_02-04.png";
import sideImage3 from "../../assets/images/sider_2019_12-09.png";
import { Row, Col, Typography } from "antd";
import { Row, Col, Typography, Spin } from "antd";
import axios from "axios";
import { RootState } from "../../redux/store";
const mapStateToProps = (state: RootState) => {
return {
loading: state.recommendProduct.loading,
error: state.recommendProduct.error,
productList: state.recommendProduct.productList,
};
};
const mapDispatchProps = (dispatch) => {
return {
// fetchStart: () => {
// dispatch(fetchRecommendProductStartActionCreator());
// },
// fetchSuccess: (data) => {
// dispatch(fetchRecommendProductSuccessActionCreator(data));
// },
// fetchFail: (error) => {
// dispatch(fetchRecommendProductFailActionCreator(error));
// },
giveMeData:()=>{
dispatch(giveMeDataActionCreator())
}
};
};
type PropsType = WithTranslation &
ReturnType<typeof mapDispatchProps> &
ReturnType<typeof mapStateToProps>;
export class HomePageComponent extends React.Component<PropsType> {
componentDidMount() {
this.props.giveMeData()
}
export class HomePageComponent extends React.Component<WithTranslation> {
// constructor(props: HomePageProps) {
// super(props);
// this.state = { : };
// }
render() {
const {t} = this.props
const { t } = this.props;
const { productList, loading, error } = this.props;
console.log("productList", productList);
// if (!productList.length) return null;
if (loading) {
return (
<Spin
size="large"
style={{
marginTop: 200,
marginBottom: 200,
marginLeft: "auto",
marginRight: "auto",
width: "100%",
}}
/>
);
}
if (error) {
return <div>网站出错:{error}</div>;
}
return (
<>
<Header />
......@@ -40,7 +100,7 @@ export class HomePageComponent extends React.Component<WithTranslation> {
</div>
</Col>
</Row>
{/* {productList.map} */}
<ProductCollection
title={
<Typography.Title level={3} type="warning">
......@@ -48,25 +108,25 @@ export class HomePageComponent extends React.Component<WithTranslation> {
</Typography.Title>
}
sideImage={sideImage1}
products={productList1}
products={productList[0].touristRoutes}
/>
<ProductCollection
title={
<Typography.Title level={3} type="danger">
{t("home_page.new_arrival")}
{t("home_page.new_arrival")}
</Typography.Title>
}
sideImage={sideImage2}
products={productList2}
products={productList[1].touristRoutes}
/>
<ProductCollection
title={
<Typography.Title level={3} type="success">
{t("home_page.hot_recommended")}
{t("home_page.hot_recommended")}
</Typography.Title>
}
sideImage={sideImage3}
products={productList3}
products={productList[2].touristRoutes}
/>
<Bussiness />
</div>
......@@ -77,5 +137,7 @@ export class HomePageComponent extends React.Component<WithTranslation> {
}
}
export const HomePage =withTranslation()(HomePageComponent)
\ No newline at end of file
export const HomePage = connect(
mapStateToProps,
mapDispatchProps
)(withTranslation()(HomePageComponent));
import * as React from "react";
import { Component } from "react";
import styles from "./studys.module.css";
import { Input ,Button} from 'antd';
import { Input, Button, Menu, Dropdown, message } from "antd";
import { DownOutlined } from "@ant-design/icons";
import { useSelector } from "../../redux/hooks";
import { useDispatch } from "react-redux";
import { type } from "os";
import {
changeInputActionCreator,
addCityActionCreator,
} from "../../redux/citys/cityActions";
export const Studys: React.FC = () => {
const dispatch = useDispatch();
const cityList =useSelector((state)=>state.city.cityLists)
const cityName =useSelector((state)=>state.city.cityName)
const cityInput =useSelector((state)=>state.city.cityInput)
const addCity =()=>{
console.log(cityInput)
}
const changeInput=(e)=>{
const cityList: { name: string }[] = useSelector(
(state) => state.city.cityLists
);
const cityName = useSelector((state) => state.city.cityName);
const cityInput = useSelector((state) => state.city.cityInput);
// const onClick = ({ key }) => {
// message.info(`Click on item ${key}`);
// };
// const menu = (
// <Menu onClick={onClick}>
// <Menu.Item key="1">1st menu item</Menu.Item>
// <Menu.Item key="2">2nd menu item</Menu.Item>
// <Menu.Item key="3">3rd menu item</Menu.Item>
// </Menu>
// );
const addCity = () => {
dispatch(addCityActionCreator(cityInput));
};
const changeInput = (e) => {
// console.log(e.target.value)
const action = {
type: 'changeInput',
value: e.target.value,
};
dispatch(action)
}
dispatch(changeInputActionCreator(e.target.value));
};
return (
<>
{/* 做一个与header.tsx类似的页面 */}
<h1>练习页面</h1>
<div>
<div>添加你想去的城市:
<input placeholder="Basic usage"onChange={changeInput} style={{width:200}} value={cityInput} />
<Button type="primary" onClick={addCity} >
添加
</Button>
<div>
添加你想去的城市:
<input
placeholder="Basic usage"
onChange={changeInput}
style={{ width: 200 }}
value={cityInput}
/>
<Button type="primary" onClick={addCity}>
添加
</Button>
</div>
<h1>我最喜欢的城市:{cityName}</h1>
<h1>我想去的城市:{cityList.map((item,index)=>{
return(
<>
<span>{item.name}</span>
</>
)
})}</h1>
<h1>
我想去的城市:
{cityList.map((item, index) => {
return (
<>
<span>{item.name},</span>
</>
);
})}
</h1>
</div>
</>
);
......
export const CHANGE_INPUT ='changeInput'
export {}
\ No newline at end of file
export const CHANGE_INPUT = "changeInput";
export const ADD_CITY = "addCity";
interface changeInputActionCreator {
type: typeof CHANGE_INPUT;
payload: string;
}
interface addCityActionCreator {
type: typeof ADD_CITY;
payload: { name: string };
}
export type cityActionTypes = changeInputActionCreator | addCityActionCreator;
export const changeInputActionCreator = (
inputValue: string
): changeInputActionCreator => {
return {
type: CHANGE_INPUT,
payload: inputValue,
};
};
export const addCityActionCreator = (name: string): addCityActionCreator => {
return {
type: ADD_CITY,
payload: { name },
};
};
import {CHANGE_INPUT} from './cityActions'
import { CHANGE_INPUT, ADD_CITY, cityActionTypes } from "./cityActions";
export interface CityState {
cityInput:string | number
cityInput: string;
cityName: string;
cityLists: { name: string }[];
}
const defaultState: CityState = {
cityInput:'',
cityInput: "",
cityName: "东京",
cityLists: [
{
......@@ -13,14 +13,19 @@ const defaultState: CityState = {
},
],
};
export default (state = defaultState, action) => {
//eslint-disable-next-line
export default (state = defaultState, action: cityActionTypes) => {
switch (action.type) {
case CHANGE_LANGUAGE:
i18n.changeLanguage(action.payload); //此处会导致不是纯函数
return { ...state, language: action.payload };
case CHANGE_INPUT:
return { ...state, cityInput: action.payload };
case ADD_CITY:
// console.log(action.payload,'action.payload')
return {
...state,
cityLists: [...state.cityLists,action.payload],
cityInput: "",
};
default:
return state;
}
};
};
import { ThunkAction } from "redux-thunk";
import { RootState } from "../store";
import axios from "axios";
export const FETCH_RECOMMEND_PRODUCTS_START = "FETCH_RECOMMEND_PRODUCTS_START"; // 正在调用推荐信息api
export const FETCH_RECOMMEND_PRODUCTS_SUCCESS =
"FETCH_RECOMMEND_PRODUCTS_SUCCESS"; // 推荐信息api调用成功
export const FETCH_RECOMMEND_PRODUCTS_FAIL = "FETCH_RECOMMEND_PRODUCTS_FAIL"; // 推荐信息api调用失败
interface FetchRecommendProductStartAction {
type: typeof FETCH_RECOMMEND_PRODUCTS_START;
}
interface FetchRecommendProductSuccessAction {
type: typeof FETCH_RECOMMEND_PRODUCTS_SUCCESS;
payload: any;
}
interface FetchRecommendProductFailAction {
type: typeof FETCH_RECOMMEND_PRODUCTS_FAIL;
payload: any;
}
export type RecommendProductAction =
| FetchRecommendProductStartAction
| FetchRecommendProductSuccessAction
| FetchRecommendProductFailAction;
export const fetchRecommendProductStartActionCreator =
(): FetchRecommendProductStartAction => {
return {
type: FETCH_RECOMMEND_PRODUCTS_START,
};
};
export const fetchRecommendProductSuccessActionCreator = (
data
): FetchRecommendProductSuccessAction => {
return {
type: FETCH_RECOMMEND_PRODUCTS_SUCCESS,
payload: data,
};
};
export const fetchRecommendProductFailActionCreator = (
error
): FetchRecommendProductFailAction => {
return {
type: FETCH_RECOMMEND_PRODUCTS_FAIL,
payload: error,
};
};
export const giveMeDataActionCreator =
(): ThunkAction<void, RootState, undefined, RecommendProductAction> =>
async (dispatch, getState) => {
dispatch(fetchRecommendProductStartActionCreator)
try {
const { data } = await axios.get(
"http://123.56.149.216:8080/api/productCollections"
);
dispatch(fetchRecommendProductSuccessActionCreator(data))
// this.setState(
// {
// loading: false,
// error: null,
// productList: data,
// },
// () => {
// console.log(this.state.productList);
// }
// );
} catch (error) {
dispatch(fetchRecommendProductFailActionCreator(error))
// this.setState({
// error: error.message,
// loading: false,
// });
}
};
import {
RecommendProductAction,
FETCH_RECOMMEND_PRODUCTS_FAIL,
FETCH_RECOMMEND_PRODUCTS_START,
FETCH_RECOMMEND_PRODUCTS_SUCCESS,
} from "./recommendProductActions";
interface RecommendProductsState {
productList: any[];
loading: boolean;
error: string | null;
}
const defaultState: RecommendProductsState = {
loading: true,
productList: [],
error: null,
};
// eslint-disable-next-line import/no-anonymous-default-export
export default (state = defaultState, action: RecommendProductAction) => {
switch (action.type) {
case FETCH_RECOMMEND_PRODUCTS_START:
return { ...state, loading: true };
case FETCH_RECOMMEND_PRODUCTS_SUCCESS:
return { ...state, loading: false, productList: action.payload };
case FETCH_RECOMMEND_PRODUCTS_FAIL:
return { ...state, loading: false, error: action.payload };
default:
return state;
}
};
import { createStore ,combineReducers} from "redux";
import { createStore ,combineReducers,applyMiddleware} from "redux";
import languageReducer from "./language/languageReducer";
import CityReducer from './citys/cityReducer'
import recommendProductsReducer from "./recommendProducts/recommendProductsReducer";
import thunk from 'redux-thunk'
const rootReducer = combineReducers({
language:languageReducer,
city:CityReducer
city:CityReducer,
recommendProduct:recommendProductsReducer
})
const store = createStore(rootReducer);
const store = createStore(rootReducer,applyMiddleware(thunk));
export type RootState =ReturnType<typeof store.getState>
export default store;
......@@ -2717,6 +2717,13 @@ axe-core@^4.0.2:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.2.1.tgz#2e50bcf10ee5b819014f6e342e41e45096239e34"
integrity sha512-evY7DN8qSIbsW2H/TWQ1bX3sXN1d4MNb5Vb4n7BzPuCwRHdkZ1H2eNLuSh73EoQqkGKUtju2G2HCcjCfhvZIAA==
 
axios@^0.21.1:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
dependencies:
follow-redirects "^1.10.0"
axobject-query@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
......@@ -5271,7 +5278,7 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
 
follow-redirects@^1.0.0:
follow-redirects@^1.0.0, follow-redirects@^1.10.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==
......@@ -9987,6 +9994,11 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
 
redux-thunk@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
redux@^4.0.0, redux@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.0.tgz#eb049679f2f523c379f1aff345c8612f294c88d4"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment