Header
组件中使用
import { Component } from 'react'
import { withRouter, RouteComponentProps } from 'react-router-dom'
import { MenuInfo } from 'rc-menu/lib/interface'
import { nanoid } from 'nanoid'
// 使用react-redux
import { Dispatch } from 'redux'
import { connect } from 'react-redux'
import store, { RootState } from 'redux/store'
import { addLanguageActionCreator, changeLanguageActionCreator } from 'redux/language/actionCreators'
const mapStateToProps = (state: RootState) => {
return {
lng: state.lng,
languageList: state.languageList
}
}
const mapDispatchToProps = (dispatch: Dispatch) => {
return {
addLanguageDispatch: (language: { code: string, language: string }) => {
dispatch(addLanguageActionCreator(language))
}
changeLanguageDispatch: (lng: 'en'|'zh') => {
dispatch(changeLanguageActionCreator(lng))
}
}
}
class HeaderComponent extends Component<RouteComponentProps & ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>>{
render(){
const { history, lng, languageList, addLanguageDispatch, changeLanguageDispatch } = this.props
/* meun 的点击事件 */
const oprateLanguage = ( e: MenuInfo ) => {
if(e.key !== 'new'){
changeLanguageDispatch(e.key)
}else{
addLanguageDispatch({code: `lng${nanoid()}`, language: '新语种'})
}
}
const menu = (
<Menu>
<Menu.Item key='new' onClick={oprateLanguage}>
添加新语言
</Menu.Item>
{languageList.map(language => (
<Menu.Item key={language.code} onClick={oprateLanguage}>
{language.language}
</Menu.Item>
))}
</Menu>
)
return (
<div>
<Typography.Text className='mr40'>让旅游更幸福</Typography.Text>
<Dropdown overlay={menu}>
<Button>
{languageList.find(language => language.code === lng)?.language}
<GlobalOutlined />
</Button>
</Dropdown>
</div>
)
}
}
export const Header = connect(mapStateToProps, mapDispatchToProps)(withRouter(HeaderComponent))
store
数据封装
- 新建目录:
src/redux
、src/redux/language
- 新建文件:
src/redux/store.ts
、src/redux/language/actionCreators.ts
,src/redux/language/reducers.ts
mkdir src/redux src/redux/language
touch src/redux/language/actionCreators.ts src/redux/language/reducer.ts
touch src/redux/product/actions.ts src/redux/product/reducer.ts
import { createStore, combineReducers } from 'redux'
import languageReducer form './language/reducer.ts'
import productReducer form './product/reducer.ts'
// 使用 combineReducers方法,连接多个reducer
const rootReducer = combineReducers({
language: languageReducer,
product: productReducer
})
const store = createStore(rootReducer)
// 使用ts的条件类型 ReturnType<T>,T:函数类型。 获取函数返回值的类型
export type RootState = ReturnType<typeof store.getState>
export default store
- product:-
product/actions.ts
、product/reducers.ts
actions.ts
// fetch_start 主要是用来控制loading, 开始发接口,loading值为true
export const FETCH_START = 'product/fetch_start'
// fetch_success 主要用来 接口数据成功,将数据data存入store
export const FETCH_SUCCESS = 'product/fetch_success'
export const FETCH_FAIL = 'product/fetch_fail'
interface ActionFetchStartProps { type: typeof FETCH_START}
interface ActionFetchSuccessProps { type: typeof FETCH_SUCCESS, payload: any}
interface ActionFetchFailProps { type: typeof FETCH_FAIL }
export type ActionsProductProps = ActionFetchStartProps | ActionFetchSuccessProps | ActionFetchFailProps
// actionCreator
export const fetchStartActionCreator = (): ActionFetchStartProps => ({ type: FETCH_START})
export const fetchSuccessActionCreator = (data:any):ActionFetchSuccessProps => ({ type: FETCH_SUCCESS, payload: data })
export const fetchFailActionCreator = ():ActionFetchFailProps => ({ type: FETCH_FAIL })
reducer.ts
import { ActionsProductProps, FETCH_START, FETCH_SUCCESS, FETCH_FAIL } from './actions.ts'
interface ProductState {
loading: boolean,
productList: any[]
}
const defaultState: ProductState = {
loading: false,
productList: []
}
export default (state = defaultState, action:ActionsProductProps ) => {
switch (action.type) {
case FETCH_START:
return { ...state, loading: true }
case FETCH_SUCCESS:
return { ...state, loading: false, tourists: action.payload }
case FETCH_FAIL:
return { ...state, loading: false }
default:
return state
}
}
- language:-
language/actions.ts
、language/reducers.ts
actions.ts
/* 用常量定义action.type,减少代码敲错 */
export const ADD_LANGUAGE = 'language/add'
export const CHANGE_LANGUAGE = 'language/change'
/* action的类型申明 */
const AddActionProps = {
type: typeof ADD_LANGUAGE,
payload: { code: string, language: string }
}
const ChangeActionProps = {
type: typeof CHANGE_LANGUAGE,
payload: 'zh' | 'en'
}
export type LanguageActionProps = AddActionProps | ChangeActionProps
/* 用工厂模式创建action */
export const addLanguageActionCreator = (language: {code: string, language: string}):ADD_LANGUAGE => {
return {
type: ADD_LANGUAGE,
payload: language
}
}
export const changeLanguageActionCreator = (lng: 'zh' | 'en'):CHANGE_LANGUAGE => {
return {
type: CHANGE_LANGUAGE,
payload: lng
}
}
2. `reducer.ts`
import { ADD_LANGUAGE, CHANGE_LANGUAGE, LanguageActionProps } from './actions'
export interface LanguageState {
lng: 'zh' | 'en',
languageList: {code: string, language: string}[]
}
const defaultStoreState: LanguageState = {
lng: 'zh',
languageList: [{ code: 'zh', language: '中文'}, { code: 'en', language: 'English'}]
}
export default (state = defaultStoreState, action:LanguageActionProps) => {
switch (action.type) {
case CHANGE_LANGUAGE:
return { ...state, lng: action.payload }
case ADD_LANGUAGE:
return { ...state, languageList: [...state.languageList, action.payload] }
default:
return state
}
}