redux和react-redux的区别:
- reduc可以在各种框架中使用(vue,angular,jquery…),不局限于react
- react-redux为react特定的状态管理容器,依赖于redux
redux基本使用
在使用react-redux之前先学习下redux的使用redux中文api地址
redux涉及几个重要部分Action,reducer,store,state,描述如下(粘贴自官网):
Action:是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。
reducer: 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state
store:就是把Action和Reducer联系到一起的对象
根据自己理解三者关系图
组件内部通过store.dispatch(action)将action传给store,接收的action通过reducer函数来进行逻辑判断,返回新的store
使用如下:
- 确保安装node,构建项目
npx create-react-app my-app
- 安装redux
npm install --save redux
- 进入项目
cd my-app
,运行npm start
- 删除不必要的文件,构建项目结构如下
action/index.js
上面提到过action是一个有效载荷,我的理解是在定义state的时候,把所有的state放到action中,无论是常量还是action创建函数,在需要触发store状态变化的时候,从定义的action文件中集中取action对象
export const COLOR_ONE = "color one";
export const COLOR_TWO = "color two";
export function get_des(obj) {
return { type: "COLOR_DES", title: obj.title, text: obj.text };
}
reducer/index.js
写reducer函数的时候要先明确自己的state树结构
import { COLOR_ONE, COLOR_TWO } from "../action";
const initState = {
COLOR_ONE: COLOR_ONE,
COLOR_TWO: COLOR_TWO,
COLOR_OBJ: { title: "default title", text: "default description" }
};
const reducer = (state = initState, action) => {
console.log("reducer---------", state, action); //app.js中dispatch后调用reducer函数
switch (action.type) {
case "COLOR_DES":
return Object.assign({}, state, {
COLOR_OBJ: {
title: action.title,
text: action.text
}
});
default:
return state;
}
};
export default reducer;
store/index.js
import { createStore } from "redux";
import reducer from "../reducer";
const store = createStore(reducer);
export default store;
app.js
import React from "react";
import store from "./store";
import {get_des} from "./action";
store.dispatch(get_des({title:"App页面标题",text:"App页面描述"})); //触发状态更改
function App() {
return (
<div className="App">
</div>
);
}
export default App;
运行控制台输出如下
可以看到在app.js页面dispatch的内容在reducer函数中被打印,说明更改状态成功
在其它组件内可以通过引入store,调用store.getState()方法获取state
react-redux基本使用
项目构建过程同redux,除了redux外再安装react-redux npm install react-redux --save
具体使用参见react-redux使用 ,这里列举下connect方法的使用
参数名 | 类型 | 说明 |
---|---|---|
mapStateToProps(state,ownProps) | Function | 这个函数允许我们将store中的数据作为props绑定到组件上 state:redux中的store ownProps:自己的props |
mapDispatchToProps(dispatch,ownProps) | Function | 将action作为props绑定到我们自己的函数中 dispatch:store.dispatch() ownProps:自己的props |
mergeProps(stateProps,dispatchProps,ownProps) | Function | 不管是stateprops还是dispatchprops,都需要和ownprops合并之后才能赋值给组件,通常情况下你可以不传这个参数,connect就会使用Object.assign替代 |
options | Object | 可以定制connector的行为 |
app下有两个子组件分别是Boy和Girl,Boy组件发射爱心,Girl组件接收
react-redux项目目录结构如下
action/index.js
export function sendAction() {
return { type: "send_heart" };
}
export function stopSend() {
return { type: "stop_heart" };
}
reducer/index.js
const initState = {
status: true
};
const reducer = (state = initState, action) => {
console.log("reducer------", state);
switch (action.type) {
case "send_heart":
return {
status: true
};
case "stop_heart":
return {
status: false
};
default:
return state;
}
};
export default reducer;
store/index.js
import { createStore } from "redux";
import reducer from "../reducer";
const store = createStore(reducer);
export default store;
boy/index.js
import React, { useState } from "react";
import {sendAction,stopSend} from "../../action";
import { connect } from "react-redux";
function Boy(props) {
const send = "send heart";
const stop = "stop send heart";
const [status, setStatus] = useState(props.status);
function changeStatus() {
status ? props.stop_heart() : props.send_heart();
setStatus(!status);
}
return (
<>
<h1>{status ? send : stop}</h1>
<button onClick={() => changeStatus()}>{status ? stop : send}</button>
</>
);
}
const mapStateToProps = state => {
return state;
};
const mapDispatchToProps = dispatch => {
return {
send_heart: () => {
dispatch(sendAction());
},
stop_heart: () => {
dispatch(stopSend());
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Boy);
girl/index.js
**import React from "react";
import { connect } from "react-redux";
function Girl(props) {
console.log(props);
return (
<>
<h1>{props.status?"发送图片":"停止发送"}</h1>
</>
);
}
const mapStateToProps = state => {
return state;
};
export default connect(mapStateToProps)(Girl);
app.js
import React from "react";
import { Provider } from "react-redux";
import Boy from "./pages/Boy";
import Girl from "./pages/Girl";
import store from "./store";
function App() {
return (
<Provider store={store}>
<div className="App">
<Boy />
<Girl />
</div>
</Provider>
);
}
export default App;