//app.js//引入react-redux相关方法import { Provider } from 'react-redux'//引入redux相关方法import { createStore, applyMiddleware } from 'redux';//引入合并过后的reducerimport rootReducer from './reducers';//引入中间件redux-sagaimport createSagaMiddleware from 'redux-saga';//引入saga的相关方法import rootSaga from './saga';//讲reducer方法和中间件saga引入到store中const sagaMiddleware = createSagaMiddleware();const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));sagaMiddleware.run(rootSaga);export default class App extends Component { render() { //此处省略其他业务代码 .... return ( //此处省略其他业务代码 .... ); }}/** * Render the main compoent */render( , document.getElementById('app'));
//container.jsimport React, { Component } from 'react';import PropTypes from 'prop-types';//引入react-redux组件的connect方法import { connect } from 'react-redux';import ExampleComponent from './component';import ExampleActions from './actions';//此方法实现了传入UI组件的props的items的监听,一旦数据有更新,便会自动更新const mapStateToProps = (state) => { return { //注意:此处由于reducers处使用了combineReducers将多个reduce合并,每个reducer中可能会有同名的state值 //所以state.example.items中的example一定要加,不然会报错 items: state.example.items }};//此方法实现了传入UI组件dispach方法const mapDispatchToProps = (dispatch) => { return { getItems: () => dispatch(ExampleActions.getItems()) }};//通过redux中的connect方法将原来的简单的展示组件变成高阶组件const ExampleContainer= connect(mapStateToProps, mapDispatchToProps)(ExampleComponent);//将容器组件ExampleContainer暴露出来给view层使用export default ExampleContainer;
//componment.jsimport React, { Component } from 'react';import PropTypes from 'prop-types';class ExampleComponent extends Component { static propTypes = { //通过PropTypes方法检查容器组件通过connect传进来的属性和方法 items: PropTypes.object, getItems: PropTypes.func, //此处省略其他业务代码 .... }; //在需要的地方调用触发函数 componentDidMount() { if (this.props.getItems) { this.props.getItems() } } render() { const { items, //此处省略其他业务代码 .... } = this.props; //在需要的地方使用传进来的数据 Object.keys(items).map((index) => { let item = items[index]; //此处省略其他业务代码 .... ); }); return ( //此处省略其他业务代码 .... ); }}export default ExampleComponent;
//actions.jsimport { ITEMS_GET_FETCH } from './actionTypes'class ExampleActions { getItems(searchs) { return { type: ITEMS_GET_FETCH, } }}//讲实例化后的ExampleActions暴露给容器组件使用export default new ExampleActions;
//saga.jsimport { ITEMS_GET, ITEMS_GET_FETCH} from './actionTypes'//引入effects API的call, put, takeEvery方法import {call, put, takeEvery} from 'redux-saga/effects';//引入封装fetch方法的cfetchimport {cfetch, checkStatus, parseJSON} from '../../utils/cfetch';//worker saga这里其实是有接收参数的 这个参数action就是redux执行dispatch方法中的参数function* fetchGetItems(){ try { const p =function () { return cfetch('/clients/name') .then(checkStatus) .then(parseJSON) .then(function (json) { return json }); }; //执行异步函数,此时本次的worker saga事件会暂停直到异步函数执行完成 //当前是一个Promise,在该Promise的状态从pending转到resolve或reject之前,当前worker saga变出于暂停状态 //若状态为resolve,则将带着返回值继续执行 //若状态为reject,则将在Generator中抛出一个错误,被catch捕获 const data = yield call(p); //指示中间件发起一个action到Store层,作用和 redux 中的 dispatch相同, 这个 effect 是非阻塞型的 //会异步执行,整个Generator执行完毕 yield put({type: ITEMS_GET, clients: Object.assign({},data)}); } catch (e) { console.log(e); }}//watcher sagafunction* rootSaga() { //监听来自action层的触发,拦截到后调用对应的worker saga(本例子中的fetchGetItems) //takeEvery允许多个worker saga实例同时启动 yield takeEvery(ITEMS_GET_FETCH, fetchGetItems);}export default rootSaga;
import { ITEMS_GET } from './actionTypes'//定义数据的初始值const initialState = { items: {},};const exampleReducer = (state = initialState, action) => { switch (action.type) { //sage层拦截到action的触发,进行一系列异步操作然后触发reducer如下,并将action传进来 //这里的state不是覆盖,而是将原来的state和更新的内容合并生成新的state,然后交给store处理 case ITEMS_GET: return {...state, items: action.items}; default: return state; }};export default exampleReducer;