redux、react-redux、redux-thunk、redux-saga使用及dva对比
一、redux使用
Redux的核心概念其实很简单:将需要修改的state都存入到store里,发起一个action用来描述发生了什么,用reducers描述action如何改变state tree 。创建store的时候需要传入reducer,真正能改变store中数据的是store.dispatch API。
1、src下新建store文件夹,新建index.js作为store的输出文件 2、store文件夹下新建index.js文件 3、新建reducer.js,actionTypes.js文件 4、组件引入store import React,{ Component } from ‘react‘; import { Input,Button,List } from ‘antd‘; import store from ‘./store‘; import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from ‘./store/actionTypes‘ class TodoList extends Component { constructor(props) { super(props); this.state = store.getState(); this.handleStoreChange = this.handleStoreChange.bind(this); this.handleBtnClick = this.handleBtnClick.bind(this); this.handleInputChange = this.handleInputChange.bind(this); store.subscribe(this.handleStoreChange) } handleInputChange(e) { const action = { type: CHANGE_INPUT_VALUE,value: e.target.value } store.dispatch(action) } handleBtnClick() { const action = { type: ADD_TODO_ITEM } store.dispatch(action) } render() { return ( <div style={{marginTop:‘20px‘,marginLeft:‘15px‘}}> <div> <Input value={this.state.inputValue} placeholder="input" style={{width:‘300px‘}} onChange={this.handleInputChange} /> <Button onClick={this.handleBtnClick} type="primary">Primary</Button> </div> <List style={{marginTop:‘15px‘,width:‘300px‘}} bordered dataSource={this.state.list} renderItem={(item,index) => <List.Item onClick={this.handleItemDelete.bind(this,index)}>{item}</List.Item>} /> </div> ) } handleStoreChange() { this.setState(store.getState()) } handleItemDelete(index) { const action = { type: DELETE_TODO_ITEM,index } store.dispatch(action) } } export default TodoList; 5、使用redux-devtool import { createStore } from ‘redux‘; import reducer from ‘./reducer‘ const store = createStore( reducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() ); export default store; ?6、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‘; 7、reducer.js代码如下 import {CHANGE_INPUT_VALUE,DELETE_TODO_ITEM} from ‘./actionTypes‘ const defaultState = { inputValue:‘aaa‘,list:[‘1‘,‘2‘] } export default (state = defaultState,action) => { if(action.type === CHANGE_INPUT_VALUE) { const newState = JSON.parse(JSON.stringify(state)); newState.inputValue = action.value; return newState; } if(action.type === ADD_TODO_ITEM) { const newState = JSON.parse(JSON.stringify(state)); newState.list.push(newState.inputValue); newState.inputValue = ‘‘; return newState; } if(action.type === DELETE_TODO_ITEM) { const newState = JSON.parse(JSON.stringify(state)); newState.list.splice(action.index,1); return newState; } return state; } 8、优化:使用actionCreactor.js来统一管理action 二、引入react-redux1.在index.js里引入react-redux及store import React from ‘react‘; import ReactDOM from ‘react-dom‘; import ‘antd/dist/antd.css‘; import ‘./index.css‘; import App from ‘./TodoList‘; import * as serviceWorker from ‘./serviceWorker‘; import store from ‘./store‘ import { Provider } from ‘react-redux‘; const ProviderApp = ( <Provider store={store}> <App></App> </Provider> ) ReactDOM.render(ProviderApp,document.getElementById(‘root‘)); serviceWorker.unregister(); 2.在组件里做connect import React,List } from ‘antd‘; import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM} from ‘./store/actionTypes‘ import {connect} from ‘react-redux‘; class TodoList extends Component { render() { const {handleInputChange,handleBtnClick} = this.props return ( <div style={{marginTop:‘20px‘,marginLeft:‘15px‘}}> <div> <Input value={this.props.inputValue} placeholder="input" style={{width:‘300px‘}} onChange={handleInputChange} /> <Button onClick={handleBtnClick} type="primary">Primary</Button> </div> <List style={{marginTop:‘15px‘,width:‘300px‘}} bordered dataSource={this.props.list} renderItem={(item,index) => <List.Item>{item}</List.Item>} /> </div> ) } } const mapStateToProps = (state) => { return { inputValue: state.inputValue,list : state.list } } const mapDispatchToProps = (dispatch) => { return { handleInputChange(e) { const action = { type: CHANGE_INPUT_VALUE,value: e.target.value } dispatch(action) },handleBtnClick() { const action = { type: ADD_TODO_ITEM } dispatch(action) },} } export default connect(mapStateToProps,mapDispatchToProps)(TodoList); 三、redux-thunk使用1.中间件的概念 dispatch一个action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware。你可以利用 Redux middleware 来进行日志记录、创建崩溃报告、调用异步接口或者路由等等。 2.引入redux-thunk import { applyMiddleware,createStore } from ‘redux‘; import thunk from ‘redux-thunk‘; const store = createStore( reducers,applyMiddleware(thunk) ); 3.这样就可以再actionCreactor中创建一个带异步函数的方法了 export const getTodoList = () => { return () => { axios.get(‘./list‘).then((res)=>{ const data = res.data; const action = initListAction(data); StorageEvent.dispatch(action); }) } } ? 四、redux-saga使用redux-saga是一个用于管理redux应用异步操作的中间件,redux-saga通过创建sagas将所有异步操作逻辑收集在一个地方集中处理,可以用来代替redux-thunk中间件。 1.在store.js里引入redux-saga import { createStore,applyMiddleware } from ‘redux‘ import createSagaMiddleware from ‘redux-saga‘ import reducer from ‘./reducers‘ import mySaga from ‘./sagas‘ // 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; 2.新建?saga.js import { call,put,takeEvery,takeLatest } from ‘redux-saga/effects‘ import Api from ‘...‘ // worker Saga: will be fired on USER_FETCH_REQUESTED actions function* fetchUser(action) { try { const user = yield call(Api.fetchUser,action.payload.userId); yield put({type: "USER_FETCH_SUCCEEDED",user: user}); } catch (e) { yield put({type: "USER_FETCH_FAILED",message: e.message}); } } function* mySaga() { yield takeEvery("USER_FETCH_REQUESTED",fetchUser); } export default mySaga; ?五、dva对比dva使用可以参考这个博客:https://www.cnblogs.com/superSmile/p/9972344.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |