React 是由 Facebook 推出的一个前端框架,它能够实现组件的复用与开发效率的提升。Redux 与 React-Router 则是成为 React 生态中必不可少的两个组成部分。Redux 提供了一种可预测的状态管理方案,React-Router 则提供了一种可实现页面级别路由的方案。本文将详细介绍 Redux 与 React-Router 的灵活使用方法。
Redux
如果你使用 React 进行过复杂应用的开发,你一定会遇到以下问题:
- 状态难以控制:组件之间的状态传递难以维护,当组件嵌套层数增加时,状态传递变得极其繁琐。
- 同步混乱:组件之间的数据交互难以进行同步,数据的修改容易导致程序状态混乱。
- 数据管理困难:组件之间的数据管理难以进行统一,难以知道哪些数据被用了,哪些数据没有被用到。
Redux 提供了一种可预测的状态管理方案。Redux 可以将所有状态保存在单独的 store 中,组件之间通过 dispatch({ type: 'xxx', payload: data }) 来触发数据状态的更新和交互。当某个组件触发了状态更新,所有依赖这个状态的组件都将得到更新的状态,这样就实现了数据状态的同步,无需考虑数据管理统一性的问题。
下面是一份 Redux 的基本示例代码:
- 定义 Action
export const incrementAction = () => ({ type: 'INCREMENT' }); // 增加计数器的 Action
export const decrementAction = () => ({ type: 'DECREMENT' }); // 减少计数器的 Action- 定义 Reducer
// www.javascriptcn.com code example
const initState = { count: 0 }; // 定义初始状态
const reducers = (state = initState, action) => { // 定义 Reducer
switch (action.type) {
case 'INCREMENT': // 自增
return { count: state.count + 1 };
case 'DECREMENT': // 自减
return { count: state.count - 1 };
default: // 不是我们定义的 ActionType,直接返回 state
return state;
}
};
export default reducers; // 导出 reducers- 定义 Store
import { createStore } from 'redux';
import reducers from './reducer';
const store = createStore(reducers); // 创建 Store
export default store; // 导出 Store- 在组件中使用
// www.javascriptcn.com code example
import React from 'react';
import { connect } from 'react-redux'; // 引入 connect 方法
import { incrementAction, decrementAction } from './action'; // 引入 Action
const Counter = ({ count, increment, decrement }) => (
<div>
<button onClick={increment}>+</button>
<span>{count}</span>
<button onClick={decrement}>-</button>
</div>
);
// mapStateToProps 函数用于组件数据的导入
const mapStateToProps = ({ count }) => ({ count });
// mapDispatchToProps 函数用于触发事件的导入
const mapDispatchToProps = (dispatch) => ({
increment: () => dispatch(incrementAction()), // 触发增加 Action
decrement: () => dispatch(decrementAction()), // 触发减少 Action
});
// 鉴于 React 组件是纯组件,我们需要外部传入 store 数据,以 props 的形式引入
export default connect(mapStateToProps, mapDispatchToProps)(Counter);React-Router
React-Router 提供了一种可实现页面级别路由的方案,不仅仅是 URL 改变,还能保证页面路由的推进与后退,帮助我们实现单页面应用(SPA),通过不同 URL 的请求,渲染同一个页面不同的组件。
下面是一份基本的 React-Router 的示例代码:
- 定义路由
// www.javascriptcn.com code example
import React from 'react';
import { Router, Route, Link, browserHistory } from 'react-router';
import Foo from './Foo';
import Bar from './Bar';
const Routes = () => (
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="foo" component={Foo} />
<Route path="bar" component={Bar} />
<Route path="*" component={NotFound} />
</Route>
</Router>
);- 定义组件并引用路由
// www.javascriptcn.com code example
import React from 'react';
import { Link } from 'react-router';
const Navbar = () => (
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/foo">Foo</Link></li>
<li><Link to="/bar">Bar</Link></li>
</ul>
);
export default Navbar;import React from 'react';
const App = ({ children }) => (
<div>
<Navbar />
{children}
</div>
);Redux 和 React-Router 的结合使用,能够实现更加完美的页面状态管理,同时实现单页面应用的高效开发。下面我们将介绍 Redux 与 React-Router 的灵活使用方法。
- 定义 Reducer
// www.javascriptcn.com code example
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import counter from '../counter/reducer';
const rootReducer = combineReducers({
routing: routerReducer, // 绑定 React-Router 的 Reducer
counter,
});
export default rootReducer;- 定义 Store
// www.javascriptcn.com code example
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk';
import rootReducer from './rootReducer';
import history from './history';
const middlewares = [
thunk,
routerMiddleware(history), // 绑定 React-Router 的 middleware
];
const composeEnhancers = composeWithDevTools({
// Specify here name, actionsBlacklist, actionsCreators and other options if needed
});
const store = createStore(
rootReducer,
composeEnhancers(applyMiddleware(...middlewares)),
);
export default store;- 定义路由
// www.javascriptcn.com code example
import React from 'react';
import { Router, Route, IndexRoute } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import App from './App';
import Home from './Home';
import Foo from './Foo';
import Bar from './Bar';
import store from './store';
import history from './history';
const syncHistory = syncHistoryWithStore(history, store); // 将 React-Router 与 Redux Store 绑定
const Routes = () => (
<Router history={syncHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home} />
<Route path="foo" component={Foo} />
<Route path="bar" component={Bar} />
</Route>
</Router>
);
export default Routes;- 定义组件并引用
// www.javascriptcn.com code example
import React from 'react';
import { connect } from 'react-redux';
import { incrementAction, decrementAction } from './action';
const Counter = ({ count, increment, decrement }) => (
<div>
<button onClick={increment}>+</button>
<span>{count}</span>
<button onClick={decrement}>-</button>
</div>
);
const mapStateToProps = ({ counter }) => ({
count: counter.count,
});
const mapDispatchToProps = (dispatch) => ({
increment: () => dispatch(incrementAction()),
decrement: () => dispatch(decrementAction()),
});
export default connect(mapStateToProps, mapDispatchToProps)(Counter);通过配置好的 Store,我们可以在不同的页面中使用相同的 Store 来管理状态,从而实现了多个页面间状态的同步,便于数据的交互操作。
通过绑定了 React-Router 的 middleware,我们可以 action 触发 URL 的变化而实现页面的路由,从而实现单页面应用(SPA)的路由功能。
本文详细介绍了 Redux 和 React-Router 的用法以及结合使用方法,它们能够帮助我们提升开发效率,降低代码复杂性。如果您有其他问题或建议,欢迎在评论区留言。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67cfb213e46428fe9eb87d35