美文网首页
React+Redux

React+Redux

作者: 琳媚儿 | 来源:发表于2020-05-12 16:48 被阅读0次

[阮一峰]
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html

Redux 的适用场景:多交互、多数据源

1用户的使用方式复杂
2.不同身份的用户有不同的使用方式(比如普通用户和管理员)
3.多个用户之间可以协作
4.与服务器大量交互,或者使用了 WebSocket
5.View要从多个来源获取数据

从组件角度看,如果你的应用有以下场景,可以考虑使用 Redux。

1.某个组件的状态,需要共享
2.某个状态需要在任何地方都可以拿到
3.一个组件需要改变全局状态
4.一个组件需要改变另一个组件的状态

发生上面情况时,如果不使用 Redux 或者其他状态管理工具,不按照一定规律处理状态的读写,代码很快就会变成一团乱麻。你需要一种机制,可以在同一个地方查询状态、改变状态、传播状态的变化。

在react 项目终端安装Redux

 npm i redux react-redux redux-thunk

<Provider> 组件

Provider组件的出现是作为中间件降低各组件与Store之间的耦合。
connect方法生成容器组件以后,需要让容器组件拿到state对象,才能生成 UI 组件的参数。

一种解决方法是将state对象作为参数,传入容器组件。但是,这样做比较麻烦,尤其是容器组件可能在很深的层级,一级级将state传下去就很麻烦。

React-Redux 提供Provider组件,可以让容器组件拿到state
首先,对原组件进行了封装: render方法中, 渲染了其子级元素, 使整个应用成为Provider的子组件。

import { Provider} from 'react-redux';
  <Provider store={store}>
            用Redux容器将状态保存起来
  </Provider>
image

第一步触发action 操作

import { fetchPosts } from '../actions/postActions';
    componentDidMount() {
        this.props.fetchPosts();
        
    }

第二部进行分发操作

异步操作至少要送出两个 Action:用户触发第一个 Action,这个跟同步操作一样,
没有问题;如何才能在操作结束时,系统自动送出第二个 Action 呢?
奥妙就在 Action Creator 之中。
异步组件:
加载成功后(componentDidMount方法),
它送出了(dispatch方法)一个 Action,向服务器要求数据
这里的fetchPosts就是 Action Creator

fetchPosts是一个Action Creator(动作生成器)

export const FETCH_POSTS = "FETCH_POSTS";

代码优化es6格式

import {
    FETCH_POSTS,
} from './types';

export const fetchPosts = () => dispatch => {
    fetch("https://jsonplaceholder.typicode.com/posts")
        .then(res => res.json())
        .then(posts =>
            dispatch({
                type: FETCH_POSTS,
                payload: posts
            })
        )
}

分发操作成功后,将dispatch和数据递交到store中,store得到action,

第三步:Store

store得到的action 传给postReducer,reducer得到状态,会进行判断到底执行的是哪一个类型

Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store

Redux 提供createStore这个函数,用来生成 Store。

import { createStore } from 'redux'
const store = createStore(fn);

createStore 方法可以接受整个应用的初始状态作为参数,那样的话,applyMiddleware就是第三个参数了

中间件

Reducer在异步操作结束后自动执行 ->用到中间件middleware
createStore方法可以接受整个应用的初始状态作为参数,那样的话,applyMiddleware就是第三个参数了。

(1.)createStore方法可以接受整个应用的初始状态作为参数,那样的话,applyMiddleware就是第三个参数了

const store = createStore(
  reducer,
  initial_state,
  applyMiddleware(logger)
);

中间件的次序有讲究。

        const store = createStore(
            reducer,
            applyMiddleware(thunk, promise, logger)
        );

applyMiddlewares()

applyMiddleware方法的三个参数,就是三个中间件。有的中间件有次序要求,使用前要查一下文档。比如,logger就一定要放在最后,否则输出结果会不正确。
applyMiddlewares()
:它是 Redux 的原生方法,作用是将所有中间件组成一个数组,依次执行
中间件内部(middlewareAPI)可以拿到getState和dispatch这两个方法。

redux-thunk 中间件

异步操作至少要送出两个 Action:用户触发第一个 Action,这个跟同步操作一样,没有问题;如何才能在操作结束时,系统自动送出第二个 Action 呢?

奥妙就在 Action Creator 之中。
加载成功后(componentDidMount方法),它送出了(dispatch方法)一个 Action,向服务器要求数据 fetchPosts(selectedSubreddit)。这里的fetchPosts就是 Action Creator
下面就是fetchPosts的代码,关键之处就在里面

export const fetchPosts = () => dispatch => {
    fetch("https://jsonplaceholder.typicode.com/posts")
        .then(res => res.json())
        .then(posts =>
            dispatch({
                type: FETCH_POSTS,
                payload: posts
            })
        )
}

这样的处理,就解决了自动发送第二个 Action 的问题。但是,又带来了一个新的问题,Action 是由store.dispatch方法发送的。而store.dispatch方法正常情况下,参数只能是对象,不能是函数。

这时,就要使用中间件redux-thunk

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducers';

// Note: this API requires redux@>=3.1.0
const store = createStore(
  reducer,
  applyMiddleware(thunk)
);

上面代码使用redux-thunk中间件,改造store.dispatch,使得后者可以接受函数作为参数。

因此,异步操作的第一种解决方案就是,写出一个返回函数的 Action Creator,然后使用redux-thunk中间件改造store.dispatch

import { createStore, applyMiddleware,compose } from 'redux';
import thunk from 'redux-thunk';
import rootReducers from './reducers/index';
const initialStore = {};
const middleware = [thunk];

export const store = createStore(
    rootReducers,
    initialStore,
    compose(
        applyMiddleware(...middleware),
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    )
   
)

第四步Reducers

Store收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer
Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

const reducer = function (state, action) {
  // ...
  return new_state;
};
import {
    FETCH_POSTS,
} from '../actions/types';
const inittialState = {
    items: [],
}

export default function (state = inittialState, action) {
    console.log("reducers")
    switch (action.type) {

        case FETCH_POSTS:
            return {
                ...state, //由actions中的postActions type返回新数据
                items: action.payload //将得到最新的状态给
            }
                default:
                    return state;
    }
}

将最新的状态给posts组件

import {combineReducers} from 'redux';
import postReducer from './postReducer';
export default combineReducers({
    posts1:postReducer  
})

Redux 提供了一个combineReducers方法,用于 Reducer 的拆分。你只要定义各个子 Reducer 函数,然后用这个方法,将它们合成一个大的 Reducer。
你只要定义各个子 Reducer函数,然后用这个方法,将它们合成一个大的 Reducer。
这种写法有一个前提,就是 State的属性名必须与子 Reducer同名

最后一步,将最新的state 返回给Posts 组件

connect()

React-Redux 提供connect()方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来

import { connect } from 'react-redux'

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

mapStateToProps()
获得reducers返回的最新状态

//第五步:
const mapStateToProps = state => ({
    posts: state.posts1.items
})

mapDispatchToProps()
mapDispatchToPropsconnect函数的第二个参数,用来建立 UI 组件的参数到store.dispatch方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。
如果mapDispatchToProps是一个函数,会得到dispatch和ownProps(容器组件的props对象)两个参数

import PropTypes from 'prop-types';
//定义类型
Posts.propTypes = {
    fetchPosts: PropTypes.func.isRequired,
    posts:PropTypes.array.isRequired
}

connect() 的第二个参数mapDispatchToProps()=>fetchPosts

import { fetchPosts } from '../actions/postActions';
//第五步:获得reducers返回的最新状态
const mapStateToProps = state => ({
    posts: state.posts1.items,
})
export default connect(mapStateToProps, { fetchPosts })(Posts) ;

相关文章

网友评论

      本文标题:React+Redux

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