React+Redux+Saga

参考信息
react-redux中文文档
redux-saga中文文档

项目搭建

npx create-react-app katsuki的基础上安装依赖

npm install redux --save
npm install react-redux --save
npm install history --save
npm install react-router-redux --save
npm install redux-saga --save
npm install react-router-dom --save
npm install redux-actions --save
npm install @loadable/component --save //组件按需加载

项目目录

React+Redux+Saga_第1张图片

入口

入口文件配置src\index.js

/**
 * @description 项目的根目录、webpack打包入口文件
 */
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import { BrowserRouter } from "react-router-dom";
import createHistory from "history/createBrowserHistory";
import { routerMiddleware } from "react-router-redux";
import createSagaMiddleware from "redux-saga";

import App from "./pages";
import rootSaga from "./saga";
import reducer from "./reducer";
import "./index.css";

const history = createHistory();

const sagaMiddleware = createSagaMiddleware(rootSaga);
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  reducer,
  composeEnhancers(applyMiddleware(routerMiddleware(history), sagaMiddleware))
);

sagaMiddleware.run(rootSaga);

ReactDOM.render(
  <Provider store={store}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </Provider>,
  document.getElementById("root")
);

export { history };

action

通过react-reduxconnect导入页面中,以type触发sagareducer
src\action\katsuki.js

export function katsukiInit() {
    return {
        type: 'do/katuski-init'
    }
}

saga

入口文件src\saga\index.js

/**
 * @description 这里所有子saga文件的根文件
 * @function all redux-saga/effects中间件的工具函数连接所有的子saga
 * @function rootSaga 执行异步编程的函数
 */
import { fork, all } from 'redux-saga/effects'

import katsuki from './katsuki'

function* rootSaga() {
  yield all([
    fork(katsuki),
  ])
}

export default rootSaga

src\saga\katsuki.js

import { takeEvery, select, put, call } from 'redux-saga/effects'

function* handleKatsukiInit(action) {
  try {
    yield put({
        type: 'success/katsuki-age',
        age: 18,
    })

  } catch (error) {
    console.log(error)
  }
}

function* katsuki() {
  yield* [
    takeEvery('do/katuski-init', handleKatsukiInit),
  ]
}

export default katsuki

reducer

入口文件src\reducer\index.js

/**
 * @description 这里所有子reducer文件的根文件
 */
import { combineReducers } from 'redux'

import katsuki from './katsuki'

const rootReducer = combineReducers({
  katsuki,
})

export default rootReducer

src\reducer\katsuki.js

import { handleActions } from 'redux-actions'
const katsuki = handleActions(
    {
        'success/katsuki-age'(state, action) {
            return {
                ...state,
                age: action.age
            }
        }
    },
    {
        age: 20,
    }
)
export default katsuki

pages

页面路由文件src\pages\Engine.js

import React, { Fragment } from 'react'
import { Switch, Route, Redirect } from 'react-router'

import loadable from '@loadable/component'
const KatsukiPage = loadable(() => import('./KatsukiPage'))

function Engine() {
  return (
    <Fragment>
      <Switch>
        <Route exact path="/katsuki" component={KatsukiPage} />
        <Redirect to="/katsuki" />
      </Switch>
    </Fragment>
  )
}

export default Engine

pages入口src\pages\index.js

import React, { Component } from "react";
import { withRouter } from "react-router-dom";
import loadable from "@loadable/component";

const Engine = loadable(() => import("./Engine"));

class App extends Component {
  componentDidMount() {
    const { history } = this.props;
    window.$history = history;
  }

  render() {
    return <Engine />;
  }
}

export default withRouter(App);

页面中引入src\pages\KatsukiPage\index.jsx

import React, { Component } from "react";
import * as actions from "../../action/katsuki";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import styles from "./styles.css";

class KatsukiPage extends Component {
  componentDidMount() {
  	// action的方法,调用后reducer仓库值改变,20 -> 18
    this.props.katsukiInit();
  }

  render() {
    return (
        <div className={styles.container}>
        	// reducer仓库值调用
            katsukichan<span>{this.props.age}</span>
        </div>
    )
  }
}

function mapStateToProps(state) {
  // state是所有导出的reducer的仓库集合,并存到当前组件的props
  return {
    ...state.katsuki,
  };
}

function mapDispatchToProps(dispatch) {
  // dispatch用于绑定导入的actions,并存到当前组件的props
  return {
    ...bindActionCreators(actions, dispatch)
  }
}

// 让组件关联reducer,不需要的部分可null,如 connect(mapStateToProps, null)(KatsukiPage)
export default connect(mapStateToProps, mapDispatchToProps)(KatsukiPage);

你可能感兴趣的:(React)