一个 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. 最小生成树算法 prim kruskal两种算法实现 HDU-1863 畅通工程

    最小生成树 通俗解释:一个连通图,可将这个连通图删减任意条边,仍然保持连通图的状态并且所有边权值加起来的总和使其达到最小.这就是最小生成树 可以参考下图,便于理解 原来的图: 最小生成树(蓝色线): ...

  2. 使用between and 作为查询条件

  3. C语言中的常用函数_持续更新

    isspace函数: 背景:之前遇到scanf()输入时会把换行符留在输入队列的情况,如果下次要用到getchar(),但是会导致其先返回这个我们不需要的换行符:从而导致不希望出现的行为: 说明:检查 ...

  4. Applese 的毒气炸弹(最小生成树)

    链接:https://ac.nowcoder.com/acm/contest/330/G 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言5242 ...

  5. nginx安装及高可用

    nginx的安装: server1: tar zxf nginx-1.14.0.tar.gz cd nginx-1.14.0/src/core/ vim nginx.h cd /root/nginx- ...

  6. 用vector实现二维向量

    如果一个向量的每一个元素是一个向量,则称为二维向量,例如 vector<vector<int> >vv(3, vector<int>(4));//这里,两个“> ...

  7. qsor快排序以及cmp函数

    void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*)); 各参数:1 待 ...

  8. CSS background-size contain 与cover的区别

    最近在重温CSS,发现好多东西都忘了,比如background-size属性中,contain与cover的区别. 菜鸟教程上是这么说的: 有点难理解,通俗解释就是:两者均以保持图像宽高比的形式缩放来 ...

  9. Web前端常见问题

    一.理论知识 1.1.讲讲输入完网址按下回车,到看到网页这个过程中发生了什么 a. 域名解析 b. 发起TCP的3次握手 c. 建立TCP连接后发起http请求 d. 服务器端响应http请求,浏览器 ...

  10. array.map

    定义和用法 map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值. map() 方法按照原始数组元素顺序依次处理元素. 注意: map() 不会对空数组进行检测. 注意: ma ...