一个 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

代码分析:

  1. reducers: redux 中的 reducers
  2. thunk: 异步action 的插件
  3. applyMiddleware: react 的中间件,用于添加插件
  4. RouterMap: 路由配置
  5. Provider:让所有容器组件都可以访问 store
  6. 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:
  1. 该方法接受2个参数,返回一个函数,返回的函数的参数通常 是react 组件,例子是App
  2. 参数1是函数,函数接收 store 中的 state 作为参数,通常 返回 state 中的数据,例子中的App组件可以通过 this.props.userInfo 获取数据
  3. 参数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
        }
    }
}
  1. axois: ajax请求的插件
  2. 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 的例子与分析的更多相关文章

  1. [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 ...

  2. [Web 前端] React Router v4 入坑指南

    cp from : https://www.jianshu.com/p/6a45e2dfc9d9 万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个React的架子 ...

  3. React躬行记(13)——React Router

    在网络工程中,路由能保证信息从源地址传输到正确地目的地址,避免在互联网中迷失方向.而前端应用中的路由,其功能与之类似,也是保证信息的准确性,只不过来源变成URL,目的地变成HTML页面. 在传统的前端 ...

  4. React Router 4.x 开发,这些雷区我们都帮你踩过了

    前言 在前端框架层出不穷的今天,React 以其虚拟 DOM .组件化开发思想等特性迅速占据了主流位置,成为前端开发工程师热衷的 Javascript 库.作为 React 体系中的重要组成部分:Re ...

  5. React Router V4发布

    React Router V4 正式版发布,该版本相较于前面三个版本有根本性变化,遵循 Just Component 的 API 设计理念. 本次升级的主要变更有: 声明式 Declarative 可 ...

  6. React Router 4.0 体验

    React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件.所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(声明式编 ...

  7. React Router基础使用

    React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...

  8. React Router基础教程

    React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...

  9. React Router教程

    React Router教程 React项目的可用的路由库是React-Router,当然这也是官方支持的.它也分为: react-router 核心组件 react-router-dom 应用于浏览 ...

  10. 最新的chart 聊天功能( webpack2 + react + router + redux + scss + nodejs + express + mysql + es6/7)

    请表明转载链接: 我是一个喜欢捣腾的人,没事总喜欢学点新东西,可能现在用不到,但是不保证下一刻用不到. 我一直从事的是依赖angular.js 的web开发,但是我怎么能一直用它呢?看看最近火的一塌糊 ...

随机推荐

  1. memcache (持续了解ing...)

    mem cache 英[kæʃ] 美[kæʃ]vt. 贮藏; memcache是一套分布式的高速缓存系统,目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的.需要频繁访问数据库的网站访问速度提 ...

  2. CF912E Prime Gift 数学

    Opposite to Grisha's nice behavior, Oleg, though he has an entire year at his disposal, didn't manag ...

  3. kuangbin专题七 POJ3264 Balanced Lineup (线段树最大最小)

    For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One d ...

  4. Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path 树上dp

    D. The Fair Nut and the Best Path 题意:给出一张图 点有权值 边也要权值 从任意点出发到任意点结束 到每个点的时候都可以获得每个点的权值,而从边走的时候都要消耗改边的 ...

  5. linux 环境下tomcat中部署jfinal项目

    tomcat中部署jfinal项目 问题现象如下图 问题描述: 我在自己的windows7系统上tomcat下面跑这个项目没有任何问题吗,但是当我把项目上传到linux服务器上的tomcatwebap ...

  6. Kibana6.x.x——导航权限控制入门

    按如下图所示设置: 用该用户登录后,界面如图所示: 但遗憾的是,根据官方论坛的说法,其它的导航隐藏控制,暂时还不支持. 参考:https://discuss.elastic.co/t/hide-ina ...

  7. System.Collections.Generic.List<T> 与 System.Collections.ArrayList

    [推荐] System.Collections.Generic.List<T> [原因] 泛型集合类List<T>在操作值类型的集合时可以不进行 装箱/拆箱 处理. 使得性能较 ...

  8. yum安装zabbix故障报错

    装zabbix时报错 [root@zabbix ~]# rpm -ivh zabbix-server-mysql-2.2.3-1.el6.x86_64.rpm zabbix-web-mysql-2.2 ...

  9. 前端https调用后端http

    昨晚发生了一个,很........的事 我前端的域名  和后端的域名 都没有做认证,前端的访问的80 调用的后端80 然后我给前端的域名做了认证ssl,但是调用后端的时候报错 原因是  https 调 ...

  10. Qt中的布局管理器

    1. 布局管理器提供相关的类对界面组件进行布局管理,能够自动排列窗口中的界面组件,窗口变化后能自动更新界面组件的大小. 2. QLayout是Qt布局管理器的抽象基类,通过继承QLayout实现了功能 ...