redux
仅仅是用来管理组件的状态,需要满足以下条件:
- 用户使用方式复杂
- 不同的用户、不同使用方式(普通用户和管理员);
- 多个用户之间的协作;
- 与服务器有大量的交互;
- View有多个数据源。
其他场景下,能不用redux就不用,否则增加项目的复杂度。
三大特征:
- 单一的数据源,整个应用的state都存储与store对象中;
- state只读,只有触发Action(用于描述发生的事件)才能改变state;
- 使用纯函数(函数的返回值只能依赖于它的参数,相同的输入,只能得到相同的结果)执行修改。
由三个部分构成:
1. Action,描述事件,是信息的载体
2. Reducer,定义事件,规定整个应用的状态如何改变,根据Action更新Store中的状态
3. Store,存储整个应用的状态
createStore(reducer,[preloadedState],[enhancer])
创建一个store来存放应用中所有的state,并且应用中只能有一个store。
参数reducers接受两个参数:当前的state和要执行的Action,返回新的state
Store
- getState(),获取state,
- dispatch(action),分发action,触发state变化的唯一途径
- subscribe(listener),用于注册回调,监听state变化
- 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)

源码
网友评论