react-router + redux + react-redux 的例子与分析
一个 react-router + redux + react-redux 的例子与分析
index.js
import React from 'react' import ReactDom from 'react-dom' import App from './App' ReactDom.render( <App/>, document.getElementById('root') )
没什么好说的
App.js :
import React from 'react' import { createStore, applyMiddleware } from 'redux' import { Provider } from 'react-redux' import thunk from 'redux-thunk' import reducers from './reducers' import RouterMap from './router' let store = createStore(reducers, applyMiddleware(thunk)) const App = () => { return ( <Provider store={ store }> <RouterMap/> </Provider> ) } export default App
代码分析:
- reducers: redux 中的 reducers
- thunk: 异步action 的插件
- applyMiddleware: react 的中间件,用于添加插件
- RouterMap: 路由配置
- Provider:让所有容器组件都可以访问 store
- createStore: redux 生成 store 的方法
例子中的:RouterMap
import React from 'react' // react-router 相关 import { Router, Route, Switch } from 'react-router-dom' // 浏览器的History模式 import createHistory from 'history/createBrowserHistory' // 生成一个redux容器的方法 import { connect } from 'react-redux' // 一个action import { initCity } from '../actions/userinfo' // 组件 import Home from '../containers/Home' import City from '../containers/City' // 创建 history const history = createHistory() class App extends React.Component { render() { return ( <Router history={ history }> <Switch> <Route exact path="/" component={ Home }></Route> <Route path="/city" component={ City }></Route> </Switch> </Router> ) } componentDidMount() { this.props.initCity(cityName) } } function mapStateToProps(state) { return { userInfo: state.userInfo } } function mapDispatchToProps(dispatch, ownprops) { return { initCity: (cityName) => { } } } export default connect( mapStateToProps, mapDispatchToProps )(App)
代码分析:
- connect:
- 该方法接受2个参数,返回一个函数,返回的函数的参数通常 是react 组件,例子是App
- 参数1是函数,函数接收 store 中的 state 作为参数,通常 返回 state 中的数据,例子中的App组件可以通过 this.props.userInfo 获取数据
- 参数2是函数,函数接收 store 中的 dispatch作为第一个参数,通常返回提交action的一些方法,例子中的App组件可以通过 this.props.initCity(cityName) 提交action
- <Router history={ history }> : 传递history 给所有组件,组件就可以通过 this.props.history.push('路由')跳转页面, this.props.history.goBack() 方法返回
- <Route path="/city" component={ City }></Route> : 路由配置
例子中的:reducers
import { combineReducers } from 'redux' export function detailInfo(state = {}, action) { switch (action.type) { case 'GET_DETAIL_INFO': return { ...state, info: action.payload.info } case 'GET_COMMENT_LIST': return { ...state, comments: action.payload.comments } default: return state } } const initialState = {page: 0, likeList: [] } export function userInfo(state = initialState, action) { switch (action.type) { case 'USER_CURRENTCITY': return { ...state, cityName: action.payload.cityName, userName: '小名' } case 'SAVE_HOMEAD': return { ...state, homeAd: action.payload.homeAd } case 'SAVE_LIKELIST': return { ...state, page: state.page + 1, likeList: state.likeList.concat(action.payload.likeList) } case 'SET_ISLOADINGLIKELIST_FLAG': return { ...state, isLoading: action.payload.isLoading } default: return state } } export default combineReducers({ userInfo, detailInfo })
代码分析:combineReducers: 接收一个拆分后 reducer 函数组成的对象,返回一个新的 Reducer 函数
代码中的:所有action ,案例只列举:initCity
import axois from 'axios' export function getDetailInfo(shopId) { return dispatch => axois.get(`/api/detail/info/${shopId}`).then((res) => { dispatch(saveDetailInfo(res.data)) }).catch((error) => { console.log(error) }) } export function saveDetailInfo(res) { return { type: 'GET_DETAIL_INFO', payload: { info: res } } } export function getComments(shopId) { return axois.get(`/api/detail/comment/${shopId}`).then((res) => { dispatch(saveComments(res.data)) }).catch((error) => { console.log(error) }) } export function saveComments(res) { return { type: 'GET_COMMENT_LIST', payload: { comments: res } } }
- axois: ajax请求的插件
- getDetailInfo:
- 该action 返回了一个发送ajax异步请求的函数
- 异步请求成功后 触发一个action : dispatch(saveDetailInfo(res.data))
- 普通的action 通常返回一个对象,它之所以能够返回函数,是由于利用了插件“thunk'”,这个是异步action 的写法
City
import React from 'react' import { connect } from 'react-redux' import { updateCity } from '../../actions/userinfo' import Header from '../../components/Header' import CityList from '../../components/CityList' import CurrentCity from './subpages/CurrentCity' class City extends React.Component { render() { return ( <div> <Header title="选择城市" goBack={ this.goBack.bind(this) }></Header> <CurrentCity currentCityName={ this.props.userInfo.cityName }></CurrentCity> <CityList chooseCity= { this.chooseCity.bind(this) }></CityList> </div> ) } goBack() { this.props.history.goBack() } chooseCity(cityName) { localStore.setItem('USER_CURRENT_CITY', cityName) this.props.initCity(cityName) this.props.history.goBack() } } function mapStateToProps(state) { return { userInfo: state.userInfo } } function mapDispatchToProps(dispatch, ownProps) { return { initCity: (cityName) => { dispatch(updateCity(cityName)) } } } export default connect( mapStateToProps, mapDispatchToProps )(City)
goBack={ this.goBack.bind(this) } : 将组件本身的goBack方法,传递给 Header 组件 , bind的作用是:在Header组件调用该方法时,上下文为City组件的 this
Header
import React from 'react' class Header extends React.Component { render() { return ( <div id="common-header"> <span className="back-icon" onClick={ this.clickHandle.bind(this) }> <i className="icon-chevron-left"></i> </span> <h1>{ this.props.title }</h1> </div> ) } clickHandle() { window.history.back() } } export default Header
Header组件并没有用connect包装,因为它是纯显示的组件,只有跟业务相关的组件,才会用connect容器包装
react-router + redux + react-redux 的例子与分析的更多相关文章
- [Redux] Adding React Router to the Project
We will learn how to add React Router to a Redux project and make it render our root component. Inst ...
- [Web 前端] React Router v4 入坑指南
cp from : https://www.jianshu.com/p/6a45e2dfc9d9 万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个React的架子 ...
- React躬行记(13)——React Router
在网络工程中,路由能保证信息从源地址传输到正确地目的地址,避免在互联网中迷失方向.而前端应用中的路由,其功能与之类似,也是保证信息的准确性,只不过来源变成URL,目的地变成HTML页面. 在传统的前端 ...
- React Router 4.x 开发,这些雷区我们都帮你踩过了
前言 在前端框架层出不穷的今天,React 以其虚拟 DOM .组件化开发思想等特性迅速占据了主流位置,成为前端开发工程师热衷的 Javascript 库.作为 React 体系中的重要组成部分:Re ...
- React Router V4发布
React Router V4 正式版发布,该版本相较于前面三个版本有根本性变化,遵循 Just Component 的 API 设计理念. 本次升级的主要变更有: 声明式 Declarative 可 ...
- React Router 4.0 体验
React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件.所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(声明式编 ...
- React Router基础使用
React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...
- React Router基础教程
React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...
- React Router教程
React Router教程 React项目的可用的路由库是React-Router,当然这也是官方支持的.它也分为: react-router 核心组件 react-router-dom 应用于浏览 ...
- 最新的chart 聊天功能( webpack2 + react + router + redux + scss + nodejs + express + mysql + es6/7)
请表明转载链接: 我是一个喜欢捣腾的人,没事总喜欢学点新东西,可能现在用不到,但是不保证下一刻用不到. 我一直从事的是依赖angular.js 的web开发,但是我怎么能一直用它呢?看看最近火的一塌糊 ...
随机推荐
- django 学习之DRF (三)
Django学习之DRF-03 视图集 1.视图集介绍 2.视图集基本使⽤ 1.需求 使⽤视图集获取列表数据和单⼀数据 2.实现 class BookInfoV ...
- [ZJOI2009]函数 BZOJ1432
题目描述 有n 个连续函数fi (x),其中1 ≤ i ≤ n.对于任何两个函数fi (x) 和fj (x),(i != j),恰好存在一个x 使得fi (x) = fj (x),并且存在无穷多的x ...
- Arch下systemd无法开机执行rc.local之解决方法
早就发现了,Arch的systemd提供的那个 rc-local.service 貌似有问题,rc.local不会执行.因为没用rc.local,一直没管. 解决方法源自这里,需要稍加改动: http ...
- IDEA 中 使用 git(Git)
GitLab GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务.安装方法是参考GitLab在GitHub上的Wiki页面. Git Git( ...
- python内存相关问题
想要弄清楚内存相关的问题,就要理清楚:变量.内存地址.值之间的关系:1.程序里什么时候分配新的内存地址?答:1.定义一个变量,内存就开辟一个内存空间,分配一个内存地址. 特殊: 如:a=687 a=1 ...
- P4213 【模板】杜教筛
[题目链接] https://www.luogu.org/problemnew/show/P4213 给定一个正整数\(N(N\le2^{31}-1)\) 求 \(ans_1=\sum_{i=1}^n ...
- linux学习五
一.系统服务管理 1.概念 服务(service) 本质就是进程,但是是运行在后台的,通常都会监听某个端口,等待其它程 序的请求,比如(mysql , sshd 防火墙等),因此我们又称为守护进程,是 ...
- 移动性能测试 | 持续集成中的 Android 稳定性测试
前言 谈到Android稳定测试,大多数会联想到使用monkey工具来做测试.google官方提供了monkey工具,可以很快速点击被应用,之前我有一篇帖子提到了monkey工具的使用,详见: htt ...
- python3+selenium获取列表某一列的值
python3+selenium获取列表某一列的值 我们在坐自动化测试时,我们可能不想单纯的想验证一个选项卡,我们让脚本随机选择一个选项进行接下来的操作.例如我们想获取列表某一列的某一个数据(随机的) ...
- codeforces之4.1学习记录
记录一些之前没见过的代码: #include <bits/stdc++.h> using namespace std; typedef long long ll; #define INF ...