react 地区筛选_React 与 Redux 实践 —— 城市筛选面板

Redux 是 状态容器 ,提供 可预测化 的状态

要点

应用中所有的 state 都以一个对象树的形式存储在一个单一的 store 中;

唯一改变 store 的办法是触发 action,一个描述发生什么的对象;

为了描述 action 如何改变 state 树,你需要编写 reducers;

为了

所以,关于组件部分,明智的做法是在最外层上使用 Redux ,然后通过 Props 方式传值给内部子组件,使得components UI组件仅仅是 pure render (纯展示)

containers 与 components 区别对比

containers(容器组件)

components(UI组件)

Lo

最顶层,路由处理

中间和子组件

与Redux联系

读取数据

从 Redux 获取 state

从 props 获取数据

修改数据

从 Redux 派发 action

从 props 调用回调函数

例子

通过一个城市筛选面板来理解 React + Redux 的使用

c64698b45460445475aa4085838cbfb2.gif

示例demo:

编写 React 应用的时候,会有一个大致的

构建应用状态树 state 结构

编写 action (描述已发生事件的普通对象,所有修改 state 的操作都必须通过触发action)

编写 reducers (描述 action 如何改变 state tree)

编写 UI组件 components (纯组件,无状态,所有

编写 容器组件 containers (用来负责管理数据和业务逻辑,react-redux 链接components)

通过 createStore 创建store,通过 Prov

定好 state tree 后,编写actions

actions.

/**

* citypanel actions

*/

export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';

export functionsetVisibilityFilter(filter){

return { type: SET_VISIBILITY_FILTER, filter }

}

Reducers

当应用很大时,可以将它拆成多个小的 reducers,分别独立地操作 state tree 的不同部分,因为 reducer 只是函数,你可以控制它们被调用的顺序,传入附加数据,甚至编写可复用的 reducer 来处理一些通用任务,如

reducer 和 action 是好基友

./reducers/cityList.jsx

import { SET_VISIBILITY_FILTER } from '../../actions/citypanel/actions';

import { cityData } from './cityData.js';

const initialState = cityData.filter(item=> item['citynum'])

console.log(initialState)

export default functioncityList(state = initialState, action){

switch (action.type) {

case SET_VISIBILITY_FILTER:

return cityFilter(action.filter)

default:

return state

}

}

functioncityFilter(filter){

return cityData.

./reducers/index.jsx 组合所有reducers (多个的时候用)

import { combineReducers } from 'redux'

import cityList from './cityList'

//使用redux的combineReducers方法将所有reducer打包起来

const

UI组件components

宗旨就是 pure function

./components/cityList.jsx

import React from 'react';

export default ({cityList = []}) => {

return (

{

cityList.map((city,index) => {

if(city){

return

./components/letterFilter.jsx

import React from 'react';

export default ({onFilterChange}) => {

// let letterArr = new Array(26);

// for (var i = 0; i < 26; i++) {

// letterArr[i]=String.fromCharCode((65 + i));

// }

// console.log(letterArr)

let letterArr=['特大','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

return (

{

letterArr.map((letter,i) => {

return

{ onFilterChange(letter) }}>{letter}

})

}

);

}

外层组件组合letterFilter与cityList子组件, ./components/index.jsx

//此处的函数参数cityList与setVisibilityFilter是由容器组件传输

import React from 'react';

import LetterFilter from './letterFilter';

import CityList from './cityList';

import '../../styles/citypanel/index.less';

import Nav from '../nav/Nav';

export default ({cityList = [], setVisibilityFilter}) => {

return (

)

}

容器组件containers

主要是通过 react-redux 中间件提供的 connect 方法来链接 containers 与 components ,而 connect 方法提供了两个方法 mapStateToProps 与 mapDispatchToProps ,它们定义了 UI 组件的业务逻辑。前者负责输入逻辑。

mapStateToProps 将 state 映射到 UI 组件的参数(Props), mapDispatchToProps 负责输出逻辑,即将用户对 UI 组件的操作映射成 Action,也可以通过 bindActionCreators 方法将 action 的所有方法绑定到props上。

./containers/

import { bindActionCreators } from 'redux'

import { connect } from 'react-redux'

import cityPanelIndex from '../../components/citypanel/index'

import * as ctiyActions from '../../actions/citypanel/actions'

//将state.cityList绑定到props的cityList

functionmapStateToProps(state){

return {

cityList:state.cityList

}

}

//将action的所有方法绑定到props上

functionmapDispatchToProps(dispatch){

return bindActionCreators(ctiyActions,dispatch);

}

export default connect(mapStateToProps,mapDispatchToProps)(cityPanelIndex)

注册store

将 state 和 action 交给 redux 来管理

./stores/createStore.jsx

import { createStore, applyMiddleware } from 'redux'

import thunk from 'redux-thunk'

import reducer from '../reducers/citypanel'

//applyMiddleware来自redux可以包装 store 的 dispatch

//thunk作用是使action创建函数可以返回一个function代替一个action对象

const createStoreWithMiddleware = applyMiddleware(

thunk

)(createStore)

export default functionconfigureStore(initialState){

const store = createStoreWithMiddleware(reducer, initialState)

//热替换选项

if (module.hot) {

// Enable Webpack hot module replacement for reducers

module.hot.accept('../reducers/citypanel', () => {

const nextReducer = require('../reducers/citypanel')

store.replaceReducer(nextReducer)

})

}

return store

}

App主文件入口

最终Provider包装主组件(containers)

Main.jsx

/**

* citypanel主入口

*/

import React from 'react'

import { Provider } from 'react-redux'

import App from '../../containers/citypanel/App'

import configureStore from '../../stores/configureStore'

const store = configureStore()

export default () => {

return (

)

}

一个react + redux 应用完成了

演示: http://giscafer.com/react-demo-list/#/citypanel

源码: https://github.com/giscafer/react-demo-list

(完)

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值