react-redux使用
1.安装 npm install --save react-redux
2.index.js中,通过Provider 设置store
const App = (
<Provider store={store}>
<TodoList/>
</Provider>
);
3.组件中通过 connect 关联store,u获取store中的state,对store进行dispatch
//把store中的state映射成组件的props,组件中通过props拿数据
import React from "react";
import store from './store/index';
//引入antd组件Input,Button
import {
Input,
Button,
List
} from 'antd';
//引入antd css样式
import 'antd/dist/antd.css';
import {
connect
} from 'react-redux';
import {
getInputChangeAction,
getAddItemAction,
getDelItemAction
} from './store/actionCreator';
//无状态组件,只有render的组件可以改成无状态组件,不用执行生命周期函数,只是返回模板,提升性能
const TodoList = (props) => {
//结构赋值简化代码
const {
inputValue,
list,
changeInputValue,
handleBtnClick,
handleItemDelete
} = props;
return (
<div>
<div style={{marginTop:'10px'}}>
<Input placeholder="todo list"
value={inputValue}
onChange={changeInputValue}
style={{width:'300px',marginRight:'10px'}} />
<Button type="primary"
onClick={handleBtnClick}
>提交</Button>
</div>
<List style={{width:'300px',marginTop:'10px'}}
bordered
dataSource={list}
renderItem={(item,index) => (<List.Item onClick={()=>(handleItemDelete(index))}>{item}</List.Item>)}
/>
</div>
);
};
const mapStateToProps = (state) => {
return {
inputValue: state.inputValue,
list: state.list
};
}
//把store.dispatch挂载到组件的props
const mapDispatchToProps = (dispatch) => {
return {
changeInputValue(e) {
const action = getInputChangeAction(e.target.value);
dispatch(action);
},
handleBtnClick() {
const action = getAddItemAction();
store.dispatch(action);
},
handleItemDelete(index) {
const action = getDelItemAction();
store.dispatch(action);
}
};
}
//组件通过connect与store关联,store中的state发生变化时,自动更新,不需要再store.subsrible订阅
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
4.组件中只有render函数,优化成无状态组件
redux-thunk
//redux-thunk使用
//1.npm install --save redux-thunk
//2.store index.js 中引入
import {
createStore,
applyMiddleware
} from 'redux';
import reducer from './reducer';
import thunk from 'redux-thunk';
const store = createStore(reducer, applyMiddleware(thunk));
export default store;
//3.actionCreator中定义action,返回函数
import {
INPUT_CHANGE_VALUE,
ADD_LIST_ITEM,
DEL_LIST_ITEM,
INIT_TODO_LIST
} from './actionTypes';
export const getInputChangeAction = (value) => ({
type: INPUT_CHANGE_VALUE,
value
});
export const getAddItemAction = (value) => ({
type: ADD_LIST_ITEM
});
export const getDelItemAction = (index) => ({
type: DEL_LIST_ITEM,
index
});
export const initTodoListAction = (list) => ({
type: INIT_TODO_LIST,
list
});
export const initTodoListByThunk = () => {
return (dispatch) => {
var data = ['1111', '3333', '5555']
// axios.get('/list.json').then((res) => {
const action = initTodoListAction(data);
dispatch(action);
// })
}
}
// 函数做异步调用处理,返回的结果后,调用action去更新store
//4.组件中调用 异步处理action
import React, {
Component
} from "react";
import store from '../store-thunk/index';
import TodoListUI2 from './TodoListUI2';
import {
getInputChangeAction,
getAddItemAction,
getDelItemAction,
initTodoListByThunk
} from '../store-thunk/actionCreator';
class TodoListUseUI extends Component {
constructor(props) {
super(props);
// 从store中获取数据
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
//订阅store,store发生变化时,执行handleStoreChange来更新state
store.subscribe(this.handleStoreChange);
}
render() {
return (
<TodoListUI2
inputValue={this.state.inputValue}
list={this.state.list}
handleInputChange={this.handleInputChange}
handleBtnClick={this.handleBtnClick}
handleItemDelete={this.handleItemDelete}
></TodoListUI2>
);
}
componentDidMount() {
const action = initTodoListByThunk();
store.dispatch(action);
}
handleStoreChange() {
this.setState(store.getState());
}
handleInputChange(e) {
const action = getInputChangeAction(e.target.value);
store.dispatch(action);
}
handleBtnClick() {
const action = getAddItemAction();
store.dispatch(action);
}
handleItemDelete(index) {
const action = getDelItemAction();
store.dispatch(action);
}
}
export default TodoListUseUI;
redux-saga
// saga使用:
// 1.安装 npm install redux-saga --save
// 2.在store index.js中引入saga
import {
createStore,
applyMiddleware
} from 'redux';
import reducer from './reducer';
import mySaga from './sagas'
import createSagaMiddleware from 'redux-saga'
// create the saga middleware
const sagaMiddleware = createSagaMiddleware()
// mount it on the Store
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
// then run the saga
sagaMiddleware.run(mySaga)
export default store;
// 3.编写sagas.js
sagas.js
import {
put,
takeEvery
} from 'redux-saga/effects'
import axios from "axios";
import {
GET_INIT_LIST
} from './actionTypes';
import {
initTodoListAction
} from './actionCreator';
function* getInitList() {
try {
const res = yield axios.get('/list.json');
const action = initTodoListAction(res.data);
yield put(action);
} catch (e) {
console.log("请求失败");
const data = ['222', '4444']
const action = initTodoListAction(data);
yield put(action);
}
}
function* mySaga() {
yield takeEvery(GET_INIT_LIST, getInitList); //拦截 type:GET_INIT_LIST的action,进行处理
}
export default mySaga;
// 4.组件中发生action getInitListAction()
import React, {
Component
} from "react";
import store from '../store-saga/index';
import TodoListUI2 from './TodoListUI2';
import {
getInputChangeAction,
getAddItemAction,
getDelItemAction,
getInitListAction
} from '../store-saga/actionCreator';
class TodoListUseUI extends Component {
constructor(props) {
super(props);
// 从store中获取数据
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
//订阅store,store发生变化时,执行handleStoreChange来更新state
store.subscribe(this.handleStoreChange);
}
render() {
return (
<TodoListUI2
inputValue={this.state.inputValue}
list={this.state.list}
handleInputChange={this.handleInputChange}
handleBtnClick={this.handleBtnClick}
handleItemDelete={this.handleItemDelete}
></TodoListUI2>
);
}
componentDidMount() {
const action = getInitListAction(); //会被saga拦截,进行异步请求处理,初始化list
store.dispatch(action);
}
handleStoreChange() {
this.setState(store.getState());
}
handleInputChange(e) {
const action = getInputChangeAction(e.target.value);
store.dispatch(action);
}
handleBtnClick() {
const action = getAddItemAction();
store.dispatch(action);
}
handleItemDelete(index) {
const action = getDelItemAction();
store.dispatch(action);
}
}
export default TodoListUseUI;
// 5.sagas.js中拦截GET_INIT_LIST action,进行异步请求逻辑处理,
// 将返回的结果 同发送action initTodoListAction 去更新store
//
// saga使用比thunk要复杂一些,但提供很多api(put,takeEvery等),比较适合在大型项目应用