redux

仅仅是用来管理组件的状态,需要满足以下条件:

  1. 用户使用方式复杂
  2. 不同的用户、不同使用方式(普通用户和管理员);
  3. 多个用户之间的协作;
  4. 与服务器有大量的交互;
  5. View有多个数据源。

其他场景下,能不用redux就不用,否则增加项目的复杂度。

三大特征:

  1. 单一的数据源,整个应用的state都存储与store对象中;
  2. state只读,只有触发Action(用于描述发生的事件)才能改变state;
  3. 使用纯函数(函数的返回值只能依赖于它的参数,相同的输入,只能得到相同的结果)执行修改。

由三个部分构成:

1. Action,描述事件,是信息的载体

2. Reducer,定义事件,规定整个应用的状态如何改变,根据Action更新Store中的状态

3. Store,存储整个应用的状态


createStore(reducer,[preloadedState],[enhancer])

创建一个store来存放应用中所有的state,并且应用中只能有一个store。

参数reducers接受两个参数:当前的state和要执行的Action,返回新的state


Store

  1. getState(),获取state,
  2. dispatch(action),分发action,触发state变化的唯一途径
  3. subscribe(listener),用于注册回调,监听state变化
  4. replaceReducer(nextReducer),更新当前Store内的Reducer

常用getState()、dispatch(action)

combinReducers(reducers)

将多个reducer函数组合成一个reducer函数


applyMiddleware(…middlewares)

是包装了 store 的 dispatch 方法


bindActionCreates(actionCreators,dispatch)

把一个 value 为不同 action creator 的对象,转成拥有同名 key 的对象。


compose(…function)

组合组合多个函数

react-redux

<Provider store>:让组件层级中的connect()方法能够获取到Redux Store
一个容器的作用,实现store的上下文传递。

connect

从UI组件生成容器组件

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])

连接react组件和Redux,形成容器组件:

import {connect} from "react-redux";
const Count = connect()(List);

mapStateToProps和mapDispatchToProps,定义了UI组件的业务逻辑。mapStateToProps主要输入逻辑,即是将state转化为组件的props属性;mapDispatchToProps输出逻辑,将用户对UI组件操作映射为action。

如下例子:
app.js

import React from 'react';
import { Provider } from 'react-redux';
import './App.css';
import store from "./store"
import Posts from "./components/Posts";

function App() {
return (
<Provider store={store}>
<Posts />
</Provider>
);
}

export default App;

正如上文所说:store是一个保存数据的地方(容器),一个应用中只能有一个store:
store.js

import {createStore,applyMiddleware, compose} from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers/index";

const initialState ={};


const middleware =[thunk];

const store = createStore(rootReducer,initialState,compose(
applyMiddleware(...middleware),
window .__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() //在浏览器中查看redux请求的数据
));

export default store

reducers文件下创建一个index.js,组合多个reducer函数

import {combineReducers} from "redux";
import postReducer from "./postReducer";

export default combineReducers({
posts:postReducer
})

reducer函数:

//引入dispatch的type类型
import {FETCH_POST} from "../actions/types";

//reducer的作用就是返回一个新的状态
const initialState = {
//存储自己想要的状态
item:[] //访问当前文件中的时候定义一个初始状态(数据)
}

/**
* reducer是一个纯函数,接收旧的state和action,返回新的state
* @param {*} state
* @param {*} action
*/
export default function(state=initialState,action){
switch(action.type){
case FETCH_POST:
return {
...state,
item:action.payload
}
default:
return state
}
}

actions文件下创建

types.js定义操作的类型:

export const FETCH_POST = "FETCH_POST";

action.js,描述操作事件,获取数据:

import { FETCH_POST } from "./types";

export const fetchPost = () => dispatch => {
fetch("http://jsonplaceholder.typicode.com/users")
.then(res => {
return res.json()
})
.then(data => {
console.log(data)
//内容分发
dispatch({
type: FETCH_POST,
//把请求的数据返回去
payload: data
})
})
}

ui组件引用如下:

import React, { Component } from "react";
//给之前的状态规定一个数据类型,
import propTypes from 'prop-types';

//在posts中使用fetchpost方法,需要用reducer中提供的connect来连接

import { connect } from 'react-redux';
import { fetchPost } from "../actions/allAction"
class Posts extends Component {
//数据从redux中拿取,则不需要使用constructor了
componentDidMount() {
this.props.fetchPost()
}
render() {
console.log(this.props)
const postItem = this.props.posts.map((item) => (
<div key={item.id}>
<h3>name:{item.name}</h3>
<p>email:{item.email}</p>
</div>
))
return <div>{postItem}</div>
}
}

/**
* 把返回的状态转化为我们的属性props
*/
const mapStateToProps = state=>({
/**
* state中的posts,是在reducers中index.js定义的posts
* item中posts的属性在postReducer.js定义的初始值
*/
posts:state.posts.item
});

//规范方法和状态的使用类型
Posts.propTypes={
fetchPost:propTypes.func.isRequired,
posts:propTypes.array.isRequired
}

/**
* connet接受两个参数(方法)
* connet(mapStateToProps,{fetchPost})
*/
export default connect(mapStateToProps,{fetchPost})(Posts)

redux、react-redux状态管理应用_数据源


​源码​