react项目使用redux入门-2-工厂模式action分离优化
场景:切换语言
-
安装
redux
依赖包npm i redux --save
-
新建目录
- 新建目录:
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 touch src/redux/language/reducer.ts
store.ts
import { createStore } from 'redux' import languageReducer form './language/reducer.ts' const store = createStore(languageReducer) export default store
- 工厂模式创建action-
actionCreators.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 } }
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 } }
- 新建目录:
-
Header
组件中使用store
import { Component } from 'react' import { withRouter, RouteComponentProps } from 'react-router-dom' import { MenuInfo } from 'rc-menu/lib/interface' import { nanoid } from 'nanoid' import store from 'redux/store' import { LanguageState } from 'redux/language/reducer' import { LanguageActionProps, addLanguageActionCreator, changeLanguageActionCreator } from 'redux/language/actionCreators' const interface StateProps extends LangageState {} class HeaderComponent extends Component<RouteComponentProps, StateProps>{ constructor(props:RouteComponentProps){ super(props) /* state初始化获取 store中的数据 */ const storeState = store.getState() this.state = { lng: storeState.lng, languageList: storeState.languageList } } componentDidMount(){ /* subscribe */ store.subscribe(() => { const storeState = store.getState() this.setState({ lng: storeState.lng, languageList: storeState.languageList }) }) } render(){ /* meun 的点击事件 */ const oprateLanguage = ( e: MenuInfo ) => { let action if(e.key !== 'new'){ action = changeLanguageActionCreator(e.key) }else{ action = changeLanguageActionCreator({code: `lng${nanoid()}`, language: '新语种'}) } /* dispatch */ store.dispatch<LanguageActionProps>(action) } 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> <Button.Group> <Button onClick={() => history.push('/signIn')}>登录</Button> <Button onClick={() => history.push('/register')}>注册</Button> </Button.Group> </div> ) } } export const Header = withRouter(HeaderComponent)