使用connected-react-router使router與store同步


connected-react-router是一個綁定react-router到redux的組件,來實現雙向綁定router的數據到redux store中,這么做的好處就是讓應用更Redux化,可以在action中實現對路由的操作。

這個組件的關鍵就在於使用了react-router中的一個關鍵組件,也就是ReactTraining/history,這個組件看了下文檔,作者是這么解釋的

The history library is a lightweight layer over browsers' built-in History and Location APIs. The goal is not to provide a full implementation of these APIs, but rather to make it easy for users to opt-in to different methods of navigation.

按照我的理解應該是對瀏覽器原本的history對象做了一定的增強,同時應該對ReactNative等環境做了一定的polyfill。

使用connected-react-router這個庫的關鍵點就在於創建合適的history對象

 

我當前connected-react-router的版本為v6,需要react router大於v4,並且react-redux大於v6,react大於v16.4.0

 

 先看index.js

import React from 'react';
import ReactDOM from 'react-dom'; import { Provider } from 'react-redux' import configureStore, { history } from './configureStore' import { ConnectedRouter } from 'connected-react-router' import routes from './routes' const store = configureStore() ReactDOM.render( <Provider store={store}>// Provider使用context將store傳給子組件 <ConnectedRouter history={history}>//ConnectedRouter傳遞history對象作為props { routes } </ConnectedRouter> </Provider> , document.getElementById('root'));

configureStore.js提供history與store

 
import { createBrowserHistory } from 'history'
import { applyMiddleware, compose, createStore } from 'redux'
import { routerMiddleware } from 'connected-react-router'
import createRootReducer from './reducers'

export const history = createBrowserHistory()

export default function configureStore(preloadedState) {
  const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || 
  compose
  
  const store = createStore(
    createRootReducer(history),
    preloadedState,
    composeEnhancer(
      applyMiddleware(
        routerMiddleware(history),
      ),
    ),
  )
  return store
}

 使用createBrowserHistory()創建history。

const history = createBrowserHistory()

使用redux-devtools-extension

window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__

reducers/index.js

import { combineReducers } from 'redux'
import { connectRouter } from 'connected-react-router'
import counterReducer from './counter'

const rootReducer = (history) => combineReducers({
  count: counterReducer,
  router: connectRouter(history)
})

export default rootReducer

combineReducers方法,用於 Reducer 的拆分。你只要定義各個子 Reducer 函數,然后用這個方法,將它們合成一個大的 Reducer

reducers/counter.js

const counterReducer = (state = 0, action) => {
    switch (action.type) {
      case 'INCREMENT':
        return state + 1
      case 'DECREMENT':
        return state - 1
      default:
        return state
    }
  }
  
  export default counterReducer  
View Code

routes/index.js

import React from 'react'
import { Route, Switch } from 'react-router'
import Counter from '../components/Counter'
import { Link } from 'react-router-dom'

const routes = (
  <div>
    <div>
        <Link to="/">Home</Link> 
        <Link to="/hello">Hello</Link> 
        <Link to="/counter">Counter</Link>
    </div>
    <Switch>
      <Route exact path="/" ><div>Home</div></Route>
      <Route path="/hello" ><div>Hello</div></Route>
      <Route path="/counter" component={Counter} />
      <Route ><div>No Match</div></Route>
    </Switch>
  </div>
)

export default routes

components/Counter.js

import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { increment, decrement } from '../actions/counter'

const Counter = (props) => (
  <div>
    Counter: {props.count}
    <button onClick={props.increment}>+</button>
    <button onClick={props.decrement}>-</button>
  </div>
)

Counter.propTypes = {
  count: PropTypes.number,
  increment: PropTypes.func.isRequired,
  decrement: PropTypes.func.isRequired,
}

const mapStateToProps = state => ({
  count: state.count,
})

const mapDispatchToProps = dispatch => ({
  increment: () => dispatch(increment()),
  decrement: () => dispatch(decrement()),
})

export default connect(mapStateToProps, mapDispatchToProps)(Counter)

actions/counter.js

export const increment = () => ({
  type: 'INCREMENT',
})

export const decrement = () => ({
  type: 'DECREMENT',
})
View Code

 


免責聲明!

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



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