react-router-redux与Haskell/JS集成:函数式编程的React应用
react-router-redux与Haskell/JS集成:函数式编程的React应用
项目概述
react-router-redux是一个用于保持React Router和Redux状态同步的库,它提供了简洁的绑定机制,使开发人员能够轻松地在React应用中管理路由状态。该项目的核心思想是将React Router的历史记录(history)与Redux的存储(store)进行同步,从而实现应用状态与路由状态的一致性。
注意:该项目已不再维护,推荐使用connected-react-router作为替代方案,适用于React Router 4+版本。
核心功能与实现
1. 路由状态同步
react-router-redux的核心功能是实现React Router和Redux状态的同步。它通过增强history实例,使其能够将所有接收到的位置更新同步到应用状态中。
history + store(redux) → react-router-redux → enhanced history → react-router
实现这一功能的关键代码位于src/sync.js,它创建了一个增强版的history对象,能够将位置变化同步到Redux存储中。
2. 路由Reducer
为了在Redux中存储路由状态,react-router-redux提供了一个专用的reducer。这个reducer会处理LOCATION_CHANGE类型的action,更新存储中的位置信息。
// [src/reducer.js](https://link.gitcode.com/i/68c41a326860e588820d721809bd0cad)
export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE'
const initialState = {
locationBeforeTransitions: null
}
export function routerReducer(state = initialState, { type, payload } = {}) {
if (type === LOCATION_CHANGE) {
return { ...state, locationBeforeTransitions: payload }
}
return state
}
在实际应用中,我们需要将这个reducer添加到根reducer中:
// [examples/basic/app.js](https://link.gitcode.com/i/0ea615162f9bc7f6db8c40807345d0f9)
const reducer = combineReducers({
...reducers,
routing: routerReducer
})
3. 路由中间件
为了支持通过Redux action来控制路由,react-router-redux提供了一个中间件。这个中间件能够捕获特定的路由action,并将其转换为实际的路由操作。
// [src/middleware.js](https://link.gitcode.com/i/27d77624112bbba5a5977371d1dbb57d)
import { CALL_HISTORY_METHOD } from './actions'
export default function routerMiddleware(history) {
return () => next => action => {
if (action.type !== CALL_HISTORY_METHOD) {
return next(action)
}
const { payload: { method, args } } = action
historymethod
}
}
使用时,需要将这个中间件应用到Redux store:
// [examples/server/store.js](https://link.gitcode.com/i/9d60d13b57ace3f418416257077a8dbb)
const store = createStore(
reducer,
initialState,
compose(
applyMiddleware(
routerMiddleware(history)
),
...devTools
)
)
基本使用示例
1. 配置Store和History
// [examples/basic/app.js](https://link.gitcode.com/i/0ea615162f9bc7f6db8c40807345d0f9)
import { createStore, combineReducers } from 'redux'
import { Provider } from 'react-redux'
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
import { syncHistoryWithStore, routerReducer } from 'react-router-redux'
import * as reducers from './reducers'
import { App, Home, Foo, Bar } from './components'
const reducer = combineReducers({
...reducers,
routing: routerReducer
})
const store = createStore(reducer)
const history = syncHistoryWithStore(browserHistory, store)
2. 渲染应用
// [examples/basic/app.js](https://link.gitcode.com/i/0ea615162f9bc7f6db8c40807345d0f9)
ReactDOM.render(
<Provider store={store}>
<div>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="foo" component={Foo}/>
<Route path="bar" component={Bar}/>
</Route>
</Router>
</div>
</Provider>,
document.getElementById('mount')
)
3. 通过Action控制路由
react-router-redux提供了一系列action创建器,可以用来通过Redux action来控制路由:
import { push, replace, goBack } from 'react-router-redux'
// 跳转到新页面
dispatch(push('/foo'))
// 替换当前页面
dispatch(replace('/bar'))
// 返回上一页
dispatch(goBack())
这些action创建器的实现位于src/actions.js。
服务端渲染示例
react-router-redux也支持服务端渲染,下面是一个基本示例:
// [examples/server/server.js](https://link.gitcode.com/i/db112063d60ddd618d4c324620f5ac33)
app.use(function (req, res) {
const memoryHistory = createMemoryHistory(req.url)
const store = configureStore(memoryHistory)
const history = syncHistoryWithStore(memoryHistory, store)
match({ history, routes, location: req.url }, (error, redirectLocation, renderProps) => {
if (error) {
res.status(500).send(error.message)
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search)
} else if (renderProps) {
const content = renderToString(
<Provider store={store}>
<RouterContext {...renderProps}/>
</Provider>
)
res.send('<!doctype html>\n' + renderToString(<HTML content={content} store={store}/>))
}
})
})
与函数式编程的结合
react-router-redux的设计理念与函数式编程高度契合,它通过纯函数来处理状态转换,使用不可变数据结构来存储状态。这种设计使得应用状态更加可预测,也更容易进行测试和调试。
特别是在与Haskell等函数式编程语言集成时,这种设计理念的优势更加明显。虽然本项目主要使用JavaScript实现,但它的API设计使得与Haskell等语言的互操作变得更加容易。
安装与使用
安装
npm install --save react-router-redux
或者,如果使用本项目的GitCode仓库:
git clone https://gitcode.com/gh_mirrors/re/react-router-redux
cd react-router-redux
npm install
基本使用流程
- 创建根reducer,包含routerReducer
- 创建store,并应用routerMiddleware
- 使用syncHistoryWithStore创建增强版history
- 将history传递给Router组件
- 在应用中使用路由action创建器来控制导航
总结
react-router-redux提供了一种简洁而强大的方式来集成React Router和Redux,使得路由状态成为应用状态的一部分,从而可以利用Redux的各种功能来管理和操作路由。
虽然该项目已不再维护,但它的设计思想和实现方式对于理解React应用中的状态管理和路由控制仍然具有重要的参考价值。对于新项目,建议使用其替代方案connected-react-router。
通过将路由状态纳入Redux管理,我们可以实现更强大的状态追踪、时间旅行调试和状态持久化等功能,这对于构建复杂的React应用非常有帮助。同时,这种方式也为React应用与Haskell等函数式编程语言的集成提供了便利,使得我们可以充分利用函数式编程的优势来构建更加健壮和可维护的应用。
更多推荐



所有评论(0)