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开发,但是我怎么能一直用它呢?看看最近火的一塌糊 ...
随机推荐
- python解释器安装
1. 下载安装包 1 2 https://www.python.org/ftp/python/2.7.14/python-2.7.14.amd64.msi # 2.7安装包 https: ...
- js 遍历tree的一个例子
小例子蕴含着到力量,我希望自己有改变自己生活的能力,自己有主宰自己命运的能力... 备注:这个例子有问题. <!DOCTYPE html> <html lang="en&q ...
- tomcat的热部署配置
1.什么是tomcat热部署? 所谓的tomcat热部署,就是在不重启tomcat服务器的前提下,将自己的项目部署到tomcat服务器中,这种方式是非常方便的,也称之为“开发即用”,热部署分为手动热部 ...
- P3348 [ZJOI2016]大森林(LCT)
Luogu3348 BZOJ4573 LOJ2092 题解 对于每个\(1\)操作建一个虚点,以后的\(0\)操作都连在最近建好的虚点上.这样每次整体嫁接的时候,直接把这个虚点断掉它原来的父亲,再\( ...
- Avito Cool Challenge 2018:D. Maximum Distance
D. Maximum Distance 题目链接:https://codeforces.com/contest/1081/problem/D 题意: 给出一个连通图以及一些特殊点,现在定义cost(u ...
- 2016"百度之星" - 资格赛(Astar Round1)D
Problem Description 度熊所居住的 D 国,是一个完全尊重人权的国度.以至于这个国家的所有人命名自己的名字都非常奇怪.一个人的名字由若干个字符组成,同样的,这些字符的全排列的结果中的 ...
- centos7博客的基础搭建(LNMP)
linux [root@zbb wordpress]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) nginx echo ...
- pm2 启动后台 node js
1,安装node js 参看:https://www.cnblogs.com/wf-l5201314/p/9229974.html 2,pm2安装(安装环境linux / os) 命令:npm ins ...
- CPU的CAS操作
https://blog.csdn.net/qq_35492857/article/details/78471032 https://www.cnblogs.com/gdjdsjh/p/5076815 ...
- 笔记_简明Python教程_Byte_of_Python
1. 局部变量.全局变量 局部变量: x = 50 def func(x): x = 2 print('Change local x to',x) func(x) print('x is still' ...