博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一步一步学习 ReactNative + Redux(3)
阅读量:4086 次
发布时间:2019-05-25

本文共 8488 字,大约阅读时间需要 28 分钟。

写在开始

前篇中,我们介绍了 Redux ,对 Store 、 Action 、Reducer 有了初步的了解。并配合 react-redux ,梳理了其工作流程,结合使用了 Provider 、 connect() 。
接下来,我们完成开篇任务中的最后一项,过滤显示 TODO 。http://www.jianshu.com/p/611fdc455e37

源码:

开发

我们所做任务如下:

  • 在入口文件添加一个新的初始state:
    与 todos 平级,做为当前过滤条件。
  • 创建一个子组件TodoFilterComponent
    包含3个过滤按钮AllUndoFinish,并接收一个属性为当前过滤条件,过滤按钮与当前过滤条件相同时,过滤按钮不可点击。
  • 修改容器组件HomeContainer
    引入过滤组件,并且可以设置当前过滤条件,根据过滤条件显示不同状态的 TODO 项。
  • 添加 Action
    定义ActionCreator生成设置当前过滤条件的 Action
  • 添加 Reducer:
    可以设置当前的过滤条件。

1、添加新初始 state

ReactReduxDemo/app/index.js 文件,修改如下:

import React, { Component } from 'react';import {    View,    StyleSheet,} from 'react-native';import { createStore } from 'redux';        import { Provider } from 'react-redux';     import reducers from './reducers/index';    import HomeContainer from './containers/home.container';// 这是初始数据const initState = {    todos: [        {
title:'吃早饭',status:true}, {
title:'打篮球',status:false}, {
title:'修电脑',status:false}, ], filter: 'All', // 'All'|'Undo'|'Finish' // 添加新的初始 `state`};let store = createStore(reducers, initState);export default class RootWrapper extends Component{ render(){ return (
); }}const styles = StyleSheet.create({ wrapper: { flex: 1, marginTop: 20, },});

2、创建子组件 TodoFilterComponent

新建文件 ReactReduxDemo/app/components/todo-filter.component.js, 如下:

import React, { Component } from 'react';import {    View,    Text,    TouchableOpacity,    StyleSheet,} from 'react-native';export default class TodoFilterComponent extends Component{    constructor(props){        super(props);    }    filterTodo(filter){        this.props.filterTodo && this.props.filterTodo(filter);    }    renderFilter(filter){        if(filter==this.props.filter){            return (                
{filter}
); } return (
{this.filterTodo(filter)}}>
{filter}
); } render(){ return (
{this.renderFilter('All')} {this.renderFilter('Undo')} {this.renderFilter('Finish')}
); }}const styles = StyleSheet.create({ wrapper: { flexDirection: 'row', paddingLeft: 20, paddingTop: 20, }, filter: { marginRight: 20, textDecorationLine: 'underline', }, filterCurrent:{ color: 'gray', textDecorationLine: 'none', },});

3、容器组件HomeContainer
我们在其中引入子组件TodoFilterComponent,并添加过滤方法,此方法的功能为设置当前过滤条件。

ReactReduxDemo/app/containers/home.container.js 文件,修改如下:

import React, { Component } from 'react';import {    View,    Text} from 'react-native';import { connect } from 'react-redux';import { changeTodoStatus, addNewTodo, filterTodoList } from '../actions/index';  // 引入 actionimport TodoFormComponent from '../components/todo-form.component';import TodoListComponent from '../components/todo-list.component';import TodoFilterComponent from '../components/todo-filter.component';            // 引入子组件class HomeContainer extends Component{    constructor(props){        super(props);    }    addTodo(text){        let { dispatch } = this.props;        dispatch(addNewTodo(text));    }    toggleTodo(index){        let { dispatch } = this.props;        dispatch(changeTodoStatus(index));    }    filterTodo(filter){        let { dispatch } = this.props;              // 从 props 里解构出 dispatch        dispatch(filterTodoList(filter));           // 执行过滤方法    }    render(){        return (            
{
this.addTodo(text)}} />
{
this.toggleTodo(index)}} />
{
this.filterTodo(filter)}} /> // 渲染子组件(注释会报错,请删除注释)
); }}// 基于全局 state ,哪些 state 是我们想注入的 propsfunction mapStateToProps(state){ return { todoList: state.todos, currentFilter: state.filter, // 注入新的 state 到 props }}export default connect(mapStateToProps)(HomeContainer);

4、修改 Action
添加新的 action 类型,新的 action 创建函数。
ReactReduxDemo/app/actions/index.js 文件,修改如下:

/*********************************** action 类型常量 *************************************//** * 更改 TODO 状态 * @type {String} */export const TOGGLE_TODO_STATUS = 'TOGGLE_TODO_STATUS';export const ADD_NEW_TODO = 'ADD_NEW_TODO';export const SET_FILTER = 'SET_FILTER';         // 添加新的 action 类型/*********************************** action 创建函数 *************************************//** * 更改 TODO 状态 * @param  {Number} index TODO索引 * @return {Object}       action */export function changeTodoStatus(index){    return {type: TOGGLE_TODO_STATUS, index};}export function addNewTodo(text){    return {type: ADD_NEW_TODO, text};}export function filterTodoList(filter){      // 添加新的 action 创建函数    return {type: SET_FILTER, filter};};

5、修改 Reducer

引用新的action类型,添加新的reducer函数,并在 combineReducers 中使用。

ReactReduxDemo/app/reducers/index.js文件,修改如下:

import { combineReducers } from 'redux';import { TOGGLE_TODO_STATUS, ADD_NEW_TODO, SET_FILTER } from '../actions/index';    // 引入 action ,使用 action 类型常量function todoList(state=[], action){    switch(action.type){        case TOGGLE_TODO_STATUS:            var todo = state[action.index];            return [                ...state.slice(0, action.index),                Object.assign({}, todo, {                  status: !todo.status                }),                ...state.slice(action.index + 1)            ];        case ADD_NEW_TODO:            return [                ...state,                {                    title: action.text,                    status: false,                }            ];        default :            return state;    }}function setFilter(state='', action){       // 定义了新的 reducer    switch(action.type){        case SET_FILTER:            return action.filter;        default :            return state;    }}const reducers = combineReducers({    todos: todoList,    filter: setFilter,                      // 添加了新的 reducer combine});export default reducers;

运行项目,是否显示出了过滤按钮呢?点击试试看,能否过滤?(暂时还不可以,我们需要写方法对数据进行过滤)


Paste_Image.png

过滤 TODO 显示

todo 列表有了,当前过滤条件也可以设置了。这里,我们需要完成根据当前过滤条件对 TODO 列表进行过滤显示。

我们知道,TODO 列表的显示,是根据容器组件HomeContainer给的数据来显示的,它并不知道数据的具体来源,给它什么数据它就显示什么数据(这也正是我们想要的功能)。

我们就会想到,将容器组件HomeContainer的 TODO 列表数据做修改,是不是就可以了呢?是的,确实是这样。
我们来看容器组件HomeContainer部分代码

// 基于全局 state ,哪些 state 是我们想注入的 propsfunction mapStateToProps(state){    return {        todoList: state.todos,        // <---- 这里就是给子组件展示的数据        currentFilter: state.filter,    }}

我们将其做一些修改过滤,就OK了。

ReactReduxDemo/app/containers/home.container.js文件,修改如下:

import React, { Component } from 'react';import {    View,    Text} from 'react-native';import { connect } from 'react-redux';import { changeTodoStatus, addNewTodo, filterTodoList } from '../actions/index';  import TodoFormComponent from '../components/todo-form.component';import TodoListComponent from '../components/todo-list.component';import TodoFilterComponent from '../components/todo-filter.component';            class HomeContainer extends Component{    constructor(props){        super(props);    }    addTodo(text){        let { dispatch } = this.props;        dispatch(addNewTodo(text));    }    toggleTodo(index){        let { dispatch } = this.props;        dispatch(changeTodoStatus(index));    }    filterTodo(filter){        let { dispatch } = this.props;        dispatch(filterTodoList(filter));    }    render(){        return (            
{
this.addTodo(text)}} />
{
this.toggleTodo(index)}} />
{
this.filterTodo(filter)}} />
); }}const getFilterTodos = (todos, filter) => { // 定义 TODO 过滤方法,返回新的数据 switch (filter) { case 'All': return todos; case 'Undo': return todos.filter( todo => !todo.status); case 'Finish': return todos.filter( todo => todo.status); default: throw new Error('Unknown filter: ' + filter); }}// 基于全局 state ,哪些 state 是我们想注入的 propsfunction mapStateToProps(state){ return { todoList: getFilterTodos(state.todos, state.filter), // 注入props时,调用 TODO 过滤方法 currentFilter: state.filter, }}export default connect(mapStateToProps)(HomeContainer);

运行项目,是否可以对 TODO 列表进行过滤了呢?恭喜你!!


Undo状态的TODO.png

Finish状态的TODO.png

到目前为止,我们的 ReactNative + Redux 开发示例告一小段落。
后面会有中间件、异步的的使用方法。

转载地址:http://ogeni.baihongyu.com/

你可能感兴趣的文章
Spring4的IoC和DI的区别
查看>>
springcloud 的eureka服务注册demo
查看>>
eureka-client.properties文件配置
查看>>
MODULE_DEVICE_TABLE的理解
查看>>
platform_device与platform_driver
查看>>
platform_driver平台驱动注册和注销过程(下)
查看>>
.net强制退出主窗口的方法——Application.Exit()方法和Environment.Exit(0)方法
查看>>
c# 如何调用win8自带的屏幕键盘(非osk.exe)
查看>>
build/envsetup.sh 简介
查看>>
linux怎么切换到root里面?
查看>>
安装alien,DEB与RPM互换
查看>>
编译Android4.0源码时常见错误及解决办法
查看>>
Android 源码编译make的错误处理
查看>>
linux环境下C语言中sleep的问题
查看>>
ubuntu 12.04 安装 GMA3650驱动
查看>>
新版本的linux如何生成xorg.conf
查看>>
xorg.conf的编写
查看>>
启用SELinux时遇到的问题
查看>>
virbr0 虚拟网卡卸载方法
查看>>
No devices detected. Fatal server error: no screens found
查看>>