Redux 和react-redux之间的关系
首先要理解的是:redux 是独立的,和react没有什么关系,想要在react中使用redux需要进行一些列的操作把它们连接起来,这一些列的操作即为:react-redux
为了方便使用,Redux 的作者封装了一个 React 专用的库 React-Redux(这是阮一峰说的,不是我说的)
Redux是什么?
redux 是一种数据状态管理模式,就相当于 vuex ,当我们要做的项目中有很多组件需要共享数据时,这时候就可以用 redux 搭建。
Redux的三个原则:唯一数据源,保持状态只读(只能通过调用dispach的形式来修改状态),数据改变只能通过纯函数(reducer)完成
如何搭建Redux?
redux包含3个比较重要的结构:store reducer action
redux的使用流程
1.怎么开始创建一个rudex?
安装redux
npm i redux react-redux --save
首先 从redux中引入一个creatStore 用于创建store
import {creatStore} from "redux"
const store = createStore(reducer);
这里需要传入一个纯函数 reducer 用于改变store里面所存储的状态(不可以直接操作他,具体怎么实现,稍后会讲)
2.如何获取store里面的值?
假如你要获取store里面存的状态state ,通过
store.getState()
即可获取整个State对象
3.如何修改store里面的值?
假如你想修改State里面的数据,则需要通过发送指令
store.dispach({type:“add”,num:20})
来触发reducer ,通过reducer即可改变state返回一个新的state
改变的过程是怎样的?我们需要看一下reducer里面的结构
4.reducer是什么?状态如何更新?
const reducer = (state,action)=>{
switch (action.type){
case 'add':
return state+action.num;
case 'del':
return state-action.num;
default:
return state
}
};
简单地说就是前面dispatch里面的对象会作为action参数传入reducer函数,通过switch来判断要做的是什么操作,完成相应操作后即可反回一个新的state
5.但是到这里只是有了一个新的state,要如何把它更新到dom上呢
我们需要用store.subscribe(conponent)这里的参数component就是dom视图, 实现一个监听的效果,只要state改变了,他会自动更新state到视图层
到这里基本上就完成了一个redux的基本流程
计时器例子
const Counter = ({ value, onIncrement, onDecrement }) => (
<div>
<h1>{value}</h1>
<button onClick={onIncrement}>+</button>
<button onClick={onDecrement}>-</button>
</div>
);
const reducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return state - 1;
default: return state;
}
};
const store = createStore(reducer);
const render = () => {
ReactDOM.render(
<Counter
value={store.getState()}
onIncrement={() => store.dispatch({type: 'INCREMENT'})}
onDecrement={() => store.dispatch({type: 'DECREMENT'})}
/>,
document.getElementById('root')
);
};
render();
store.subscribe(render);
既然这样就已经实现了redux,那还需要react-redux干啥?
思考一个问题,如果我要在其他页面也操作这个store,要怎么做?
redux通过编写一些列的代码可以实现这个功能,但是代码量比较大逻辑比较复杂
react-redux 就是用来解决这个问题的
它提供 provider 和 connect 两函数来解决
直接看代码
安装 redux
npm install redux react-redux --save
1.创建action
//action.js
import actionTypes from './actionTypes'
const actionCreator = {
getInputChangeAction: (val) => ({
type: actionTypes.CHANGE_INPUT_VLAUE,
value: val
}),
btnClickAction: (val) => ({
type: actionTypes.BTN_CLICK,
value: val
}),
listDelAction: (val) => ({
type: actionTypes.LIST_DEL,
index: val
})
}
export default actionCreator;
2.创建actionTypes.js
//actionTypes.js
const types = {
CHANGE_INPUT_VLAUE: 'change_input_value',
BTN_CLICK: 'btn_click',
LIST_DEL: 'list_del'
}
export default types;
3.定义reducer纯函数
//reducer.js
import actionTypes from './actionTypes';
const defaultState = {
inputValue: '',
list: [],
};
export default (state = defaultState, action) => {
// reducer 可以接受state,但是绝不能修改state
const newState = JSON.parse(JSON.stringify(state));
switch (action.type) {
case actionTypes.CHANGE_INPUT_VLAUE:
newState.inputValue = action.value;
break;
case actionTypes.BTN_CLICK:
newState.list.push(action.value);
newState.inputValue = '';
break;
case actionTypes.LIST_DEL:
newState.list.splice(action.index, 1);
break;
default:
break;
}
return newState;
};
5.创建store
//store.js
import { createStore } from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store;
6.使用用react-redux 中的provider传递store
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'
import store from './store'
import TodoList from './components/TodoList';
// if (process.env.NODE_ENV === "development") {
// require('./mock/index.js');
// }
ReactDOM.render(
<Provider store={store}>
<TodoList />
</Provider>,
document.getElementById('root')
);
TodoList.js
//TodoList.js
import React from 'react';
import { connect } from 'react-redux';
import actions from '../store/actionCreator';
//组件中创建state的映射关系
//建后传入到connect()函数中即可通过props直接访问
const mapStateToProps = state => {
return {
value: state.inputValue,
list: state.list,
};
};
//组件中创建dispatch的映射关系
//创建后传入到connect()函数中即可通过props直接调用方法
const mapDispatchToProps = dispatch => {
return {
inputChange: e => dispatch(actions.getInputChangeAction(e.target.value)),
btnClick: value => dispatch(actions.btnClickAction(value)),
listClick: index => dispatch(actions.listDelAction(index)),
};
};
// todolist组件目前只有dom可以写成函数组件以提升效率;
// ui组件
const TodoList = props => {
const { value, list, inputChange, btnClick, listClick } = props;
return (
<div>
<div>
<input onChange={inputChange} value={value}></input>
<button onClick={() => btnClick(value)}>提交</button>
</div>
<ul>
{list.map((item, index) => {
return (
<li key={index} onClick={() => listClick(index)}>
{item}
</li>
);
})}
</ul>
</div>
);
};
// 容器组件
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
这样就实现了通过react-redux管理组件状态