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开发,但是我怎么能一直用它呢?看看最近火的一塌糊 ...
随机推荐
- 查看ip常见命令...
1.获取ip Unix用户可以在命令提示符中输入ifconfig来获取. 使用Windows的用户,请尝试使用 ipconfig 命令.
- anglarJs分页
首先在页面引入分页插件 <script src="../plugins/angularjs/pagination.js"></script> <lin ...
- Android点击事件(click button)的四种写法
在学习android开发和测试的时候发现不同的人对于click事件的写法是不一样的,上网查了一下,发现有四种写法,于是想比较一下四种方法的不同 第一种方法:匿名内部类 代码: package com. ...
- python 批量修改包名
#coding=utf-8 import os #import re # 设置编码为utf-8 否则会报错..这时候 sublime控制台会报乱码.但是别担心,utf-8 文件 并不会报错 impor ...
- 剧本--ansible
剧本不喜欢, 1.1 编写剧本规范:(PYyaml语法格式文件) 剧本中有层级划分 每个层级都要用两个空格进行区分 第一级标题 第二级标题 第三级标题 强调注意:一定使用ansible软件配置剧本时, ...
- put get & push pull
总要有一个容器,一个生产方,一个消费方
- Redis未授权访问攻击过程与防范
一.Redis未授权访问攻击过程 攻击主机:kali 目标主机:centos6.8(10.104.11.178) Redis版本:2.8 攻击条件:默认配置,未进行认证 攻击步骤详解: 1.Kali攻 ...
- java生成临时令牌和访问令牌
public String getTicket(String logo, String productId) { String aTicket = ""; SimpleDateFo ...
- MVCC(Multi-Version Concurrency Control)多版本并发控制机
MVCC(Multi-Version Concurrency Control)是一种多版本并发控制机制.
- Android Studio CMake 生成多个so
生成多个so案例 这里stringFromJNI和stringFromJNI11分别是调用one-lib和two-lib两个so package com.test.ndkmoreso; import ...