Redux学习2

1.UI组件(渲染)和容器组件(逻辑)的拆分

将 TodoList.js 拆分成 容器组件TodoList.js 和 UI组件TodoListUI.js 。

(1)TodoList.js

import React, {Component} from 'react';
import 'antd/dist/antd.css';
import ToDoListUI from './TodoListUI';
import store from './store/index';
import {getInputChangeAction, getAddItemAction, getDeleteItemAction} from './store/actionCreators';

class TodoList extends Component {

    constructor(props) {
        super(props);
        this.state = store.getState();
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleStoreChange = this.handleStoreChange.bind(this);
        this.handleButtonClick = this.handleButtonClick.bind(this);
        this.handleItemDelete = this.handleItemDelete.bind(this);
        store.subscribe(this.handleStoreChange)  //store中数据改变后执行的方法
    }

    render() {
        return <ToDoListUI inputValue={this.state.inputValue} list={this.state.list}
                           handleInputChange = {this.handleInputChange}
                           handleButtonClick={this.handleButtonClick}
                           handleItemDelete={this.handleItemDelete}/>
    }

    handleInputChange(e) {
        const action=getInputChangeAction(e.target.value);
        store.dispatch(action);
    }

    handleStoreChange(){
        this.setState(store.getState());  //执行setState后,页面才会重新渲染
    }

    handleButtonClick(){
        const action = getAddItemAction();
        store.dispatch(action)
    }

    handleItemDelete(index){
        const action = getDeleteItemAction(index)
        store.dispatch(action)
    }
}

export default TodoList;

 (2)TodoListUI.js

import React,{Component} from 'react';
import {Button, Input, List} from "antd";

class TodoListUI extends Component{
    render(){
        return (
            <div style={{marginTop: 10, marginLeft: 10}}>
                <div>
                    <Input value={this.props.inputValue}
                           placeholder="todo info"
                           style={{width: 300, marginRight: '10px'}}
                           onChange={this.props.handleInputChange}/>
                    <Button type="primary" onClick={this.props.handleButtonClick}>提交</Button>
                    <List style={{marginTop: 10, width: 300}}
                          bordered
                          dataSource={this.props.list}
                          renderItem={(item,index) => (
                              <List.Item onClick={(index)=>{this.props.handleItemDelete(index)}}>{item}</List.Item>
                          )}
                    />
                </div>
            </div>
        )
    }
}

export default TodoListUI;

2.无状态组件(当一个组件内只有render()函数的时候,我们可以使用无状态组件替换之前的普通组件)

普通组件中包含render等生命周期函数,消耗性能;而无状态组件就是一个函数,因此性能高。

将上面的 UI组件TodoListUI.js 替换 为下面的无状态组件TodoListUI.js:

import React from 'react';
import {Button, Input, List} from "antd";

const TodoListUI = (props)=>{
    return (
        <div style={{marginTop: 10, marginLeft: 10}}>
            <div>
                <Input value={props.inputValue}
                       placeholder="todo info"
                       style={{width: 300, marginRight: '10px'}}
                       onChange={props.handleInputChange}/>
                <Button type="primary" onClick={props.handleButtonClick}>提交</Button>
                <List style={{marginTop: 10, width: 300}}
                      bordered
                      dataSource={props.list}
                      renderItem={(item,index) => (
                          <List.Item onClick={(index)=>{props.handleItemDelete(index)}}>{item}</List.Item>
                      )}
                />
            </div>
        </div>
    )
};

export default TodoListUI;

3.Redux中发送异步请求获取数据(与react中的ajax请求类似,只不过是通过Redux Flow流程进行)

4.使用Redux-thunk中间件进行ajax请求发送

(1)安装redux-thunk中间件:npm install redux-thunk

(2)创建store时,使用thunk中间件(同时使用devtools开发者工具)

文档:https://github.com/zalmoxisus/redux-devtools-extension中的1.2 Advanced store setup。

redux-thunk中间件:使得可以在action中写异步代码。

之前创建的action只能是js对象,使用redux-thunk后可以是函数。但store接受的action只能是对象,当store检测到action是一个函数时,会自动的执行该函数。该函数首先进行ajax获取数据,然后改变store中的数据(遵循redux流程,创建action,dispatch(action)。)

开发复杂项目时,最好将异步操作、复杂的业务逻辑,不要放在生命周期函数、组件内,将其拆分到其他地方。此处可以借助redux-thunk将其放到actionCreator中进行管理。

1.TodoList.js

import {getInputChangeAction, getAddItemAction, getDeleteItemAction, getTodoList} from './store/actionCreators';


componentDidMount() {
        const action = getTodoList();
        store.dispatch(action);  //action动作是一个函数,当处理这个action时,就会执行该函数
    }

 2.actionCreators.js

import axios from "axios";


//没有使用thunk中间件之前,action只能返回对象如上所示,使用thunk后可以返回函数
export const getTodoList = () => {
    return (dispatch)=>{
        axios.get('/list.json').then((res)=>{
            const data=res.data;
            const action = initAjaxListAction(data);
            dispatch(action);
        })
    }
};

 

上一篇:Thunk


下一篇:javascript – 使用带有promise的co库而不是thunk有什么好处?