react项目使用redux入门-3-react-redux(在class类组件中使用)
场景:切换语言
使用react-redux的步骤
- 安装
react-redux
依赖 - 在
src/index.tsx
中引入react-redux
中的Provider
,store
, 使用Provider,并加载store数据仓库react-redux
使用react
的context
上下文,提供一个Provider API
,包裹 App组件,并加载store
,提供全局的store
- 在待使用的组件中使用
react-redux
中的connect
函数。connect
其实是个 高阶hoc
,只是它没有使用 withxxx的命名规范
具体使用
-
安装
react-redux
依赖包npm i react-redux --save npm i @types/react-redux --save-dev
-
src/index.tsx
import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' // react-redux 利用上下文context,提供的数据组件Provider import 'antd/dist/antd.css' import './index.css' import App from './App' import 'i18n' import store from 'redux/store' ReactDOM.render( <React.StrictMode> {/* 使用Provider, 并加载 数据仓库 store, 就可以在全局范围内使用store */} <Provider store={store}> <App /> </Provider> </React.StrictMode>, document.getElementById('root') )
-
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' /* connect 就是一个高阶hoc,只不过它的命名没有使用withxxxx来表示,class 类组件 使用 withxxx 高阶hoc组件 使用了connect,就相当于store.subscribe, 即组件订阅了store中的数据 */ /* mapStateToProps: 处理数据的流入。返回一个对象 使用connect函数,传入mapStateToProps,完成store数据与组件的props绑定 */ // 高阶hoc包裹的组件,可以获取到一些额外的props或state属性,connect函数传入参数 mapStateToProps, 组件的props会被注入一些额外的props属性 const mapStateToProps = (state: RootState) => { return { lng: state.lng, languageList: state.languageList } } /* mapDispatchToProps: 处理数据的流出。返回一个对象,对象中的每一个字段都是一个dispatch处理函数 将dispatch绑定到props中 */ 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> <Button.Group> <Button onClick={() => history.push('/signIn')}>登录</Button> <Button onClick={() => history.push('/register')}>注册</Button> </Button.Group> </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 touch src/redux/language/reducer.ts
store.ts
import { createStore } from 'redux' import languageReducer form './language/reducer.ts' const store = createStore(languageReducer) // 使用ts的条件类型 ReturnType<T>,T:函数类型。 获取函数返回值的类型 export type RootState = ReturnType<typeof store.getState> 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 } }
- 新建目录: