首先先安装redux,可以通过yarn add redux
来安装
也可以通过
npm install --save redux
//多数情况下,你还需要使用 React 绑定库和开发者工具。
npm install --save react-redux
npm install --save-dev redux-devtools
首先需要先引入redux中createStore这个方法import { createStore } from 'redux';
,并且不能单单的创建store,需要在创建store的时候,将reducer传递进来。也就是说我们在创建store的时候,要先去创建reducer,然后将reducer传递给创建store的这个函数,然后用reducer来创建store。
reducer里返回的必须是一个函数,函数里接收两个参数,一个是state,一个action。
state = defaultState的意思是reducer负责管理整个应用里面的数据,怎么处理,怎么存都是reducer来管理的。
Redux中核心的API
createStore 创建store
store.dispatch 帮助我们派发action,这个action会传递store
store.getState() 可以帮助我们去获取store里面所有的数据内容
store.subscribe() store的改变,只要store发生改变,store.subscribe()这个函数接收的这个回调函数就会被执行
store文件夹下的index.js
import { createStore } from 'redux';
import reducer from './reducer';
// 创建数据真正存储仓库
const store = createStore(
reducer,
//如果安装了REDUX_DEVTOOLS,那么就在页面上使用这个工具
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
export default store;
reducer.js
const defaultState={
inputValue:'',
list:[]
}
// 返回一个函数
//state指的是store里面上一次存储数据,action指的是用户传过来的那句话
//reducer的作用拿到之前的数据和当前操作的信息,然后对之前的数据进行一些处理,返回一个新的数据给store
//reducer可以接受state,但是绝不能修改state,这也就是为什么要去拷贝一个副本
export default (state = defaultState, action) =>{
if(action.type === 'change_input_value'){
// 对之前的state做一次深拷贝
const newState = JSON.parse(JSON.stringify(state));
//如果你要改变inputValue,对原来store里的数据拷贝一份出来,然后把里面的inputValue改变成传递过来的新的值
newState.inputValue = action.value;
//固定写法,对newState进行一个返回,返回给了store
return newState;
}
if(action.type==='add_todo_item'){
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue='';
console.log(newState);
return newState;
}
if(action.type==='delete_todo_item'){
const newState = JSON.parse(JSON.stringify(state));
// 找到对应的下标,删除一项
newState.list.splice(action.index,1);
return newState;
}
// console.log(state,action);
return state;
}
TodoList.js
import React,{Component} from 'react';
import 'antd/dist/antd.css';
import { Input, Button, List } from 'antd';
import store from './store';
class TodoList extends Component{
constructor(props){
super(props);
this.state=store.getState();
this.handleInputChange=this.handleInputChange.bind(this);
this.handleBtnClick=this.handleBtnClick.bind(this);
this.handleStoreChange=this.handleStoreChange.bind(this);
//store里面的数据只要发生改变,subscribe里面函数就会被自动的执=行
store.subscribe(this.handleStoreChange);
}
render(){
return (
<div style={{marginTop:'10px',marginLeft:'10px'}}>
<div>
<Input
value={this.state.inputValue}
placeholder='todo info'
style={{width:'300px',marginRight:'10px'}}
onChange={this.handleInputChange}
/>
<Button type="primary" onClick={this.handleBtnClick}>提交</Button>
</div>
<List
style={{marginTop:'10px',width:'300px'}}
bordered
dataSource={this.state.list}
renderItem={(item,index) => (<List.Item onClick={this.handleItemDelete.bind(this,index)}>{item}</List.Item>)}
/>
</div>
)
}
handleInputChange(e){
// 去改变store里面的内容,首先要创建一句话,告诉store
const action = {
type: 'change_input_value',
value:e.target.value
}
// 将这句话传递给store
store.dispatch(action);
}
handleStoreChange(){
//当感知到store的数据变化的时候,调用store.getState()方法,
//从store里面重新取一次数据,然后调用setState替换当前组件里的数据
// 这样组件里的数据,就和store里的数据同步了
this.setState(store.getState());
}
handleBtnClick(){
const action = {
type:'add_todo_item'
};
store.dispatch(action);
}
handleItemDelete(index){
const action ={
type:'delete_todo_item',
index
}
store.dispatch(action);
// alert(index);
}
}
export default TodoList;
react首先要去改变store数据,去派发一个action,action会通过dispath方法传递给store,store再把之前的数据和action转发给reducer,reducer是一个函数,他接收到了state和action之后,在做一些处理之后,会返回一个新的state给到store,store用这个新的state替换掉之前store里的数据,然后store数据发生改变的时候,react组件会感知到store发生改变,这个时候从store里重新取数据,更新组件的内容,页面就跟着发生了变化
进一步改版,将Action Types进行拆分和使用actionCreator统一创建action
TodoList.js
import React,{Component} from 'react';
import 'antd/dist/antd.css';
import { Input, Button, List } from 'antd';
import store from './store';
import { getInputChangeAction, getAddItemAction, getDeleteItemAction } from './store/actionCreators';
class TodoList extends Component{
constructor(props){
super(props);
this.state=store.getState();
this.handleInputChange=this.handleInputChange.bind(this);
this.handleBtnClick=this.handleBtnClick.bind(this);
this.handleStoreChange=this.handleStoreChange.bind(this);
//store里面的数据只要发生改变,subscribe里面函数就会被自动的执=行
store.subscribe(this.handleStoreChange);
}
render(){
return (
<div style={{marginTop:'10px',marginLeft:'10px'}}>
<div>
<Input
value={this.state.inputValue}
placeholder='todo info'
style={{width:'300px',marginRight:'10px'}}
onChange={this.handleInputChange}
/>
<Button type="primary" onClick={this.handleBtnClick}>提交</Button>
</div>
<List
style={{marginTop:'10px',width:'300px'}}
bordered
dataSource={this.state.list}
renderItem={(item,index) => (<List.Item onClick={this.handleItemDelete.bind(this,index)}>{item}</List.Item>)}
/>
</div>
)
}
handleInputChange(e){
// 去改变store里面的内容,首先要创建一句话,告诉store
const action = getInputChangeAction(e.target.value);
// 将这句话传递给store
store.dispatch(action);
}
handleStoreChange(){
//当感知到store的数据变化的时候,调用store.getState()方法,
//从store里面重新取一次数据,然后调用setState替换当前组件里的数据
// 这样组件里的数据,就和store里的数据同步了
this.setState(store.getState());
}
handleBtnClick(){
const action = getAddItemAction();
store.dispatch(action);
}
handleItemDelete(index){
const action = getDeleteItemAction(index);
store.dispatch(action);
// alert(index);
}
}
export default TodoList;
store文件夹下的index.js
import { createStore } from 'redux';
import reducer from './reducer';
// 创建数据真正存储仓库
const store = createStore(
reducer,
//如果安装了REDUX_DEVTOOLS,那么就在页面上使用这个工具
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
export default store;
store文件夹下的reducer.js
import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes';
const defaultState={
inputValue:'',
list:[]
}
// 返回一个函数
//state指的是store里面上一次存储数据,action指的是用户传过来的那句话
//reducer的作用拿到之前的数据和当前操作的信息,然后对之前的数据进行一些处理,返回一个新的数据给store
//reducer可以接受state,但是绝不能修改state,这也就是为什么要去拷贝一个副本
export default (state = defaultState, action) =>{
if(action.type === CHANGE_INPUT_VALUE){
// 对之前的state做一次深拷贝
const newState = JSON.parse(JSON.stringify(state));
//如果你要改变inputValue,对原来store里的数据拷贝一份出来,然后把里面的inputValue改变成传递过来的新的值
newState.inputValue = action.value;
//固定写法,对newState进行一个返回,返回给了store
return newState;
}
if(action.type===ADD_TODO_ITEM){
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue='';
console.log(newState);
return newState;
}
if(action.type===DELETE_TODO_ITEM){
const newState = JSON.parse(JSON.stringify(state));
// 找到对应的下标,删除一项
newState.list.splice(action.index,1);
return newState;
}
// console.log(state,action);
return state;
}
store文件夹下的actionTypes.js
export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';
store文件夹下的actionCreators.js
import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes';
export const getInputChangeAction =(value)=>({
type: CHANGE_INPUT_VALUE,
value
});
export const getAddItemAction =()=>({
type: ADD_TODO_ITEM
});
export const getDeleteItemAction =(index)=>({
type: DELETE_TODO_ITEM,
index
});