react项目使用redux入门-4-react-redux(在函数式类组件中使用, 使用hook)
场景:切换语言
使用react-redux的步骤
- 安装
react-redux依赖 - 在
src/index.tsx中引入react-redux中的Provider,store, 使用Provider,并加载store数据仓库react-redux使用react的context上下文,提供一个Provider API,包裹 App组件,并加载store,提供全局的store
- 在待使用的组件中使用
react-redux中的useSelector、useDispatchhook函数。useSelector获取store中的数据useDispatch获取dispatch函数
具体使用
-
安装
react-redux依赖包npm i react-redux --save npm i @types/react-redux --save-dev -
src/index.tsximport 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({/* 使用Provider, 并加载 数据仓库 store, 就可以在全局范围内使用store */} , 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 { useDispatch, useSelctor } from 'react-redux' // const lng = useSelector(state => state.lng) /* 使用useSelctor这个hook来获取store中的数据,其中一个目的就是解决组件与store数据耦合问题。 如果每次在组 件中使用useSelector都要传入RootState类型,就讲store与组件深度绑定,就将导致组件不能复用 => 所以,需要使用 TypeUseSelectorHook 这个interface,来讲RootStore 这个类型剥离开 */ import { useDispatch } from 'react-redux' import { useSelector } from 'redux/hooks' // 使用TypeUseSelectorHook这个interface 来重新定义 useSelector这个hook import { addLanguageActionCreator, changeLanguageActionCreator } from 'redux/language/actionCreators' export const Header = () => { const lng = useSelector(state => state.lng) const languageList = useSelector(state => state.languageList) const dispatch = useDispatch() /* meun 的点击事件 */ const oprateLanguage = ( e: MenuInfo ) => { if(e.key !== 'new'){ dispatch(changeLanguageActionCreator(e.key)) }else{ dispatch(changeLanguageActionCreator({code: `lng${nanoid()}`, language: '新语种'})) } } const menu = ( ) return ( ) }让旅游更幸福 -
store数据封装- 新建目录:
src/redux、src/redux/language - 新建文件:
src/redux/store.ts、src/redux/hooks.ts、src/redux/language/actionCreators.ts,src/redux/language/reducers.ts
mkdir src/redux src/redux/language touch src/redux/store.ts src/redux/hooks.ts touch src/redux/language/actionCreators.ts touch src/redux/language/reducer.tsstore.ts
import { createStore } from 'redux' import languageReducer form './language/reducer.ts' const store = createStore(languageReducer) // 使用ts的条件类型 ReturnType,T:函数类型。 获取函数返回值的类型 export type RootState = ReturnType export default store hooks.ts
// 该文件将会导出 useSelector 与 react-redux中的 useSelector 重名, // 所以 使用 import { useSelector as useReduxSelector } from 'react-redux'进行重命名 import { useSelector as useReduxSelector, TypeUseSelectorHook } from 'react-redux' import { RootState } form 'redux/store' export const useSelector:TypeUseSelectorHook= useReduxSelector - 工厂模式创建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 } } - 新建目录: