美文网首页
07.Redux进阶(上)

07.Redux进阶(上)

作者: 小二的学习日记 | 来源:发表于2020-07-16 16:42 被阅读0次

UI组件和容器组件

在这个例子中,我们想要分离UI组件和容器组件

//===>src/TodoList.js
import React, { Component } from 'react'
import 'antd/dist/antd.css';
import store from './store/index.js'
import { getInputChangeAction, getAddItemAction, getDeleteItemAction } from './store/actionCreators'
import TodoListUI from './TodoListUI'

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.handleBtnClick = this.handleBtnClick.bind(this)
        this.handleItemDelete = this.handleItemDelete.bind(this)
        store.subscribe(this.handleStoreChange)
    }

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

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

    handleStoreChange(e) {
        this.setState(store.getState())
    }

    handleBtnClick(e) {
        const action = getAddItemAction()
        store.dispatch(action)
    }

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

export default TodoList
//===>src/TodoListUI.js
import React, { Component } from 'react'
import { Input, Button, List } from 'antd';

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

export default TodoListUI
效果和之前一样

无状态组件

因为上面TodoListUI这个组件中,只有一个render函数,所以我们可以把它定义成为一个无状态组件(性能最优)
修改TodoListUI

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

Redux 中发送异步请求获取数据

1.添加一个收到请求的actionTypes

//===>src/store/actionTypes.js
...
export const INIT_LIST_ACTION = 'init_list_action';

2.编写一个收到请求的actionCreators

//===>src/store/actionCreators.js
...
export const initListAction = (data) => ({
    type:INIT_LIST_ACTION,
    data
})

3.编写收到action的reducer的操作

//===>src/store/reducer.js
...
 if (action.type === INIT_LIST_ACTION) {
        const newState = JSON.parse(JSON.stringify(state))
        newState.list = action.data
        return newState
    }
...

4.编写异步请求逻辑,并触发action

//===>src/TodoList.js
...
  componentDidMount() {
        axios.get('/list.json').then((res) => {
            const data = res.data
            const action = initListAction(res.data)
            store.dispatch(action)
        })
    }
...
image.png

使用Redux-thunk中间件实现ajax数据请求

1.先来安装redux-thunk
npm install redux-thunk
thunk是redux实现异步请求的中间件
2.怎么使用中间件呢?我们可以参考一下文档

//===>src/store/index.js
import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import reducer from './reducer'

const composeEnhancers =
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
        window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

const enhancer = composeEnhancers(
    applyMiddleware(thunk),
    // other store enhancers if any
);
const store = createStore(reducer, enhancer);

export default store;

3.编写一个用于异步请求的action
之前,我们的action是对象,但在这里,因为使用了redux-thunk,我们可以把action写成一个函数。这样的话,我们在使用actionCreator的时候,会先的调用这个函数进行异步操作,之后,在进行后面的操作。

//===>src/store/actionCreators
...
export const getTodoList = () => {
    return (dispatch) => {
        axios.get('/list.json').then((res) => {
            const data = res.data
            const action = initListAction(data)
            dispatch(action)
        })
    }
}

4.修改TodoList组件中的钩子函数,进行异步请求

//===>src/TodoList.js
...
import { getInputChangeAction, getAddItemAction, getDeleteItemAction, getTodoList } from './store/actionCreators'
...
    componentDidMount() {
        const action = getTodoList()
        store.dispatch(action)
    }
...

效果和之前的异步请求一样

什么是Redux的中间件

image.png

Redux-saga中间件使用入门

redux-sage也是用来处理异步请求的,但是超级麻烦。他的github是redux-saga
1.安装redux-sage

npm install redux-saga

2.在项目中引入redux-sage
sagaMiddleware.run(todoSaga)这句话的意思是运行todoSage,也就是第三步中我们要编写的sages.js文件

//===>src/store/index.js
import { createStore, applyMiddleware, compose } from 'redux'
import reducer from './reducer'
import createSagaMiddleware from 'redux-saga'
import todoSaga from './sagas'

const sagaMiddleware = createSagaMiddleware()
const composeEnhancers =
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
        window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(
    applyMiddleware(sagaMiddleware),
    // other store enhancers if any
);
const store = createStore(reducer, enhancer);
sagaMiddleware.run(todoSaga)

export default store;

3.在步骤2中,我们引入了sagas这个文件,这个是要我们来自己创建的
这里function*(){}叫做generator函数,你可以百度一下。takeEvery方法可以监听到GET_INIT_LIST这个类型的action,去判断是否要执行getInitList
function* getInitList(){}方法里面的东西可以同步执行,但注意一下异常处理

//===>src/store/sages.js
import { put, takeEvery } from 'redux-saga/effects'
import { GET_INIT_LIST } from './actionTypes'
import { initListAction } from './actionCreators'
import axios from 'axios'

function* getInitList() {
    try {
        const res = yield axios.get('./list.json')
        const action = initListAction(res.data)
        yield put(action)
    } catch (e) {
        console.log('list.json 网络请求失败');
    }
}

//generator 函数
function* mySaga() {
    yield takeEvery(GET_INIT_LIST, getInitList);
}

export default mySaga;

4.接下来我们就可以编写之前的发送action的操作了

//===>src/store/actionTypes.js
...
export const GET_INIT_LIST = 'get_init_list';
//===>src/store/actionCreators.js
import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, INIT_LIST_ACTION, GET_INIT_LIST } from './actionTypes'
...
export const getInitList = () => ({
    type: GET_INIT_LIST
})
//===>src/TodoList.js
import { getInputChangeAction, getAddItemAction, getDeleteItemAction, getInitList } from './store/actionCreators'
...
    componentDidMount() {
        const action = getInitList();
        store.dispatch(action)
    }
...
效果不变

相关文章

  • 07.Redux进阶(上)

    UI组件和容器组件 在这个例子中,我们想要分离UI组件和容器组件 无状态组件 因为上面TodoListUI这个组件...

  • Python 进阶(上)

    1、如何在列表、字典、集合中根据条件筛选数据? 列表 字典 集合 2、如何为元组中的每个元素命名,提高程序可读性?...

  • 进阶班,加油吧

    进阶班开营了。 选择进阶班我的目的很简单,就是写稿上稿,有专业老师指点,只要我写就一定会上稿。 进阶班的目的也是一...

  • Android Data Binding——高级

    上一篇文章Android Data Binding——进阶介绍了Data Binding的语法等进阶功能。这一篇我...

  • 《java 进阶之路》 上

    整整一月没有更新博客了,因为十月份和双十一新入手的6本技术相关的书,这个月看完了3本,后面的3本还得慢慢肯。 下面...

  • 股市进阶之道(上)

    第一,建立正确的投资价值观;第二,掌握企业价值分析的方法论;第三,理解市场定价的内在特质和规律。 真正能长期起作用...

  • React 进阶 Redux (上)

    最开始接触 Redux 时候做 demo 时候只是照猫画虎将 redux 进入到 react 项目来使用,其实我们...

  • go 进阶—接口(上)

    参考 Understanding Go Interface感谢 francesc 分享 接口 我们编程中少不了对接...

  • webpack进阶【19】: vue-cli 脚手架环境 反向

    webpack : vue-cli 脚手架环境 代理服务器的配置 注意:本进阶在webpack进阶【18】的基础上...

  • Android MVP高级

    上一篇:Android MVP进阶 前面一篇文章,我们讲了Android MVP的进阶应用,解决了一个View空指...

网友评论

      本文标题:07.Redux进阶(上)

      本文链接:https://www.haomeiwen.com/subject/udlfhktx.html