最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

关于React实践项目的示例详解(三)

来源:懂视网 责编:小采 时间:2020-11-27 20:16:19
文档

关于React实践项目的示例详解(三)

关于React实践项目的示例详解(三):React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架。而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战!上回说到使用Redux进行状态管理,这次我们使用Redux-saga 管理 Redux 应用异步操作React 实践项目
推荐度:
导读关于React实践项目的示例详解(三):React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架。而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战!上回说到使用Redux进行状态管理,这次我们使用Redux-saga 管理 Redux 应用异步操作React 实践项目

上回说到使用Redux进行状态管理,这次我们使用Redux-saga 管理 Redux 应用异步操作

React 实践项目 (一)

React 实践项目 (二)

React 实践项目 (三)

- 首先我们来看看登陆的 Reducer

export const auth = (state = initialState, action = {}) => {
 switch (action.type) {
 case LOGIN_USER:
 return state.merge({
 'user': action.data,
 'error': null,
 'token': null,
 });
 case LOGIN_USER_SUCCESS:
 return state.merge({
 'token': action.data,
 'error': null
 });
 case LOGIN_USER_FAILURE:
 return state.merge({
 'token': null,
 'error': action.data
 });
 default:
 return state
 }
};

Sagas 监听发起的 action,然后决定基于这个 action 来做什么:是发起一个异步调用(比如一个 Ajax 请求),还是发起其他的 action 到 Store,甚至是调用其他的 Sagas。

具体到这个登陆功能就是我们在登陆弹窗点击登陆时会发出一个 LOGIN_USER action,Sagas 监听到 LOGIN_USER action,发起一个 Ajax 请求到后台,根据结果决定发起 LOGIN_USER_SUCCESSaction 还是LOGIN_USER_FAILUREaction

接下来,我们来实现这个流程

  • 创建 Saga middleware 连接至 Redux store

  • 在 package.json 中添加 redux-saga 依赖

    "redux-saga": "^0.15.4"

    修改 src/redux/store/store.js

    /**
     * Created by Yuicon on 2017/6/27.
     */
    import {createStore, applyMiddleware } from 'redux';
    import createSagaMiddleware from 'redux-saga'
    import reducer from '../reducer/reducer';
    
    import rootSaga from '../sagas/sagas';
    
    const sagaMiddleware = createSagaMiddleware();
    
    const store = createStore(
     reducer,
     applyMiddleware(sagaMiddleware)
    );
    
    sagaMiddleware.run(rootSaga);
    
    export default store;

    Redux-saga 使用 Generator 函数实现

  • 监听 action

  • 创建 src/redux/sagas/sagas.js

    /**
     * Created by Yuicon on 2017/6/28.
     */
    import { takeLatest } from 'redux-saga/effects';
    import {registerUserAsync, loginUserAsync} from './users';
    import {REGISTER_USER, LOGIN_USER} from '../action/users';
    
    export default function* rootSaga() {
     yield [
     takeLatest(REGISTER_USER, registerUserAsync),
     takeLatest(LOGIN_USER, loginUserAsync)
     ];
    }

    我们可以看到在 rootSaga 中监听了两个 action 登陆和注册 。

    在上面的例子中,takeLatest 只允许执行一个 loginUserAsync 任务。并且这个任务是最后被启动的那个。 如果之前已经有一个任务在执行,那之前的这个任务会自动被取消。

    如果我们允许多个 loginUserAsync 实例同时启动。在某个特定时刻,我们可以启动一个新 loginUserAsync 任务, 尽管之前还有一个或多个 loginUserAsync 尚未结束。我们可以使用 takeEvery 辅助函数。

  • 发起一个 Ajax 请求

  • 获取 Store state 上的数据

  • selectors.js

    /**
     * Created by Yuicon on 2017/6/28.
     */
    export const getAuth = state => state.auth;
  • api

  • api.js

    /**
     * Created by Yuicon on 2017/7/4.
     * 
     */
    
    /**
     * 这是我自己的后台服务器,用 Java 实现
     * 项目地址:
     * 文档:http://139.224.135.86:8080/swagger-ui.html#/
     */
    const getURL = (url) => `http://139.224.135.86:8080/${url}`;
    
    export const login = (user) => {
     return fetch(getURL("auth/login"), {
     method: 'POST',
     headers: {
     'Content-Type': 'application/json'
     },
     body: JSON.stringify(user)
     }).then(response => response.json())
     .then(json => {
     return json;
     })
     .catch(ex => console.log('parsing failed', ex));
    };
  • 创建 src/redux/sagas/users.js

  • /**
     * Created by Yuicon on 2017/6/30.
     */
    import {select, put, call} from 'redux-saga/effects';
    import {getAuth, getUsers} from './selectors';
    import {loginSuccessAction, loginFailureAction, registerSuccessAction, registerFailureAction} from '../action/users';
    import {login, register} from './api';
    import 'whatwg-fetch';
    
    export function* loginUserAsync() {
     // 获取Store state 上的数据
     const auth = yield select(getAuth);
     const user = auth.get('user');
     // 发起 ajax 请求
     const json = yield call(login.bind(this, user), 'login');
     if (json.success) {
     localStorage.setItem('token', json.data);
     // 发起 loginSuccessAction
     yield put(loginSuccessAction(json.data));
     } else {
     // 发起 loginFailureAction
     yield put(loginFailureAction(json.error));
     }
    }

    select(selector, ...args) 用于获取Store state 上的数据
    put(action) 发起一个 action 到 Store
    call(fn, ...args) 调用 fn 函数并以 args 为参数,如果结果是一个 Promise,middleware 会暂停直到这个 Promise 被 resolve,resolve 后 Generator 会继续执行。 或者直到 Promise 被 reject 了,如果是这种情况,将在 Generator 中抛出一个错误。

    Redux-saga 详细api文档

  • 结语

  • 我在工作时用的是 Redux-Thunk, Redux-Thunk 相对来说更容易实现和维护。但是对于复杂的操作,尤其是面对复杂异步操作时,Redux-saga 更有优势。到此我们完成了一个 Redux-saga 的入门教程,Redux-saga 还有很多奇妙的地方,

    文档

    关于React实践项目的示例详解(三)

    关于React实践项目的示例详解(三):React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架。而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战!上回说到使用Redux进行状态管理,这次我们使用Redux-saga 管理 Redux 应用异步操作React 实践项目
    推荐度:
    标签: 例子 项目 示例
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top