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)
文章评论