react項目使用redux入門-3-react-redux(在class類組件中使用)


場景:切換語言

使用react-redux的步驟

  1. 安裝 react-redux依賴
  2. src/index.tsx中引入 react-redux中的Providerstore, 使用Provider,並加載store數據倉庫
    • react-redux使用reactcontext上下文,提供一個Provider API,包裹 App組件,並加載store,提供全局的store
  3. 在待使用的組件中使用react-redux中的connect函數。
    • connect其實是個 高階hoc,只是它沒有使用 withxxx的命名規范

具體使用

  1. 安裝react-redux依賴包

    npm i react-redux --save
    npm i @types/react-redux --save-dev
    
  2. 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')
    )
    
  3. 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))
    
  4. store數據封裝

    • 新建目錄:src/reduxsrc/redux/language
    • 新建文件:src/redux/store.tssrc/redux/language/actionCreators.tssrc/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
      }
    }
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM