zoukankan      html  css  js  c++  java
  • nextjs的开发使用(二)---引入redux状态管理

    在上篇文章中,基于react的nextjs服务端渲染框架学习使用
    学习了解了一些关于nextjs的东西,并做了一个小demo,这篇文章将对上篇文章做一个补充,在nextjs中引入redux

    安装

    // 安装redux相关依赖
    yarn add redux redux-saga react-redux
    // 安装next.js对于redux的封装依赖包
    yarn add next-redux-wrapper next-redux-saga
    yarn add redux react-redux
    

    创建目录及文件

    创建redux文件夹,并在下面创建index.js,actions,reducers,rootSaga.js文件

    1、redux/index.js

    初始化store

    import { createStore, applyMiddleware } from 'redux';
    import createSagaMiddleware from 'redux-saga';
    import rootSaga from './rootSaga';
    import rootReducer from './reducers';
    
    export function initializeStore(initialState){
      // 创建一个 Saga middleware
      const sagaMiddleware = createSagaMiddleware();
    
      // 使用 applyMiddleware 将 middleware 连接至 Store
      const store = createStore(
        rootReducer,
        initialState,
        applyMiddleware(sagaMiddleware)
      );
    
      // 运行并监控各个action
      store.sagaTask = sagaMiddleware.run(rootSaga);
    
      return store
    }
    

    2、redux/action-types.js

    定义一些action常量

    // 推荐
    export const GET_RECOMMEND_LIST = "GET_RECOMMEND_LIST";
    // 获取App详情
    export const GET_APP_INFO = "GET_APP_INFO";
    

    3、redux/actions.js

    import { createActions } from 'redux-actions'
    
    // 使用createActions创建多个动作
    export const {
      getAppInfoRequest,
      getAppInfoSucceed,
      addAppInfoRequest,
      getPostsSucceed
    } = createActions({
      GET_APP_INFO_REQUEST: id => {
        return id
      },
      GET_POSTS_SUCCEED: res => {
        return res
      },
      GET_APP_INFO_SUCCEED: res => {
        return res
      },
      ADD_APP_INFO_REQUEST: data => {
        return data
      }
    })
    

    4、redux/reducers.js
    获取action传过来的数据存储到state中

    import { handleActions } from "redux-actions";
    import * as types from "./action-types";
    
    // 默认state
    let defaultState = {
      searchList: [] //搜索结果列表
    };
    
    // 使用handleActions处理多个actions ,这里通过action.payload获取传过来的数据
    const reducerCreators = handleActions(
      {
        [types.GET_APP_INFO_SUCCEED]: (state, action) => {
          return {
            ...state,
            appInfo: action.payload
          };
        },
        [types.GET_RECOMMEND_LIST_SUCCEEDED]: (state, action) => {
          return {
            ...state,
            recommendList: action.payload
          };
        }
      },
      defaultState
    );
    
    export default reducerCreators;
    

    5、redux/rootSaga.js

    import { put, call, takeLatest, all } from 'redux-saga/effects'
    import {
      getAppInfoRequest,
      getAppInfoSucceed,
      addAppInfoRequest,
      getPostsSucceed
    } from './actions'
    import $api from '../api/index.js'
    import * as fetchApi from '../utils/fetcher'
    
    /**
     *
     * 获取app详情数据
     * @param {*} action
     */
    export function* getAppInfo(action) {
      try {
        const posts = yield call(fetchApi.getPosts)
        yield put(getPostsSucceed(posts))
      } catch (error) {
        console.log(error)
      }
    }
    
    export function* addAppInfo(action) {
      console.log('action', action)
      console.log('addAppInfo process.browser', process.browser)
    }
    
    // 同时启动多个Sagas  监听action动作
    export default function* rootSaga() {
      yield all([
        // takeLatest(actionCreators.appSearch, appSearch),
        takeLatest(addAppInfoRequest, addAppInfo),
        takeLatest(getAppInfoRequest, getAppInfo)
      ])
    }
    

    redux结构改造

    从上面可以看到我们将所有的操作actions、reducers和saga中,如果项目越来越大,就会变得难以维护。下面我们按照不同的功能分别创建不同的actions、reducers和sage文件
    目录结构如下:

    redux
    |----app
        |-----saga
            |---index.js
            |---appSaga.js
        |-----actions.js
        |-----reducers.js
        |-----selectors.js
    |----project
    index.js
    rootSaga.js
    

    1、saga/index.js
    这里主要是监听action动作,触发对应的saga方法

    import { takeLatest, all } from 'redux-saga/effects'
    import { getAppInfoRequest, addAppInfoRequest } from '../actions'
    
    import { addAppInfoSaga, getAppInfoSaga } from './appSaga'
    
    // 同时启动多个Sagas  监听action动作
    export function* appWatcher() {
      yield all([
        takeLatest(addAppInfoRequest, addAppInfoSaga),
        takeLatest(getAppInfoRequest, getAppInfoSaga)
      ])
    }
    

    2、saga/appSaga.js
    在saga中发起接口请求,并将结果数据通知action保存在state中

    import * as fetchApi from '../../../utils/fetcher'
    import { put, call } from 'redux-saga/effects'
    import { getPostsSucceed } from '../actions'
    /**
     *
     * 获取app详情数据
     * @param {*} action
     */
    export function* getAppInfoSaga(action) {
      // 通过action.payload获取数据
    
      try {
        const posts = yield call(fetchApi.getPosts)
        yield put(getPostsSucceed(posts))
      } catch (error) {
        console.log(error)
      }
    }
    
    export function* addAppInfoSaga(action) {
      console.log('action', action)
      console.log('addAppInfo process.browser', process.browser)
    }
    

    3、app/actions.js
    所有的actions动作在这里统一创建

    import { createActions } from 'redux-actions'
    
    // 使用createActions创建多个动作
    export const {
      getAppInfoRequest,
      getAppInfoSucceed,
      addAppInfoRequest,
      getPostsSucceed
    } = createActions({
      GET_APP_INFO_REQUEST: id => {
        return id
      },
      GET_POSTS_SUCCEED: res => {
        return res
      },
      GET_APP_INFO_SUCCEED: res => {
        return res
      },
      ADD_APP_INFO_REQUEST: data => {
        return data
      }
    })
    

    4、app/reducers.js
    接收到action发起的动作之后,将数据保存在state中

    import { handleActions } from 'redux-actions'
    
    import { getAppInfoSucceed, getPostsSucceed } from './actions'
    
    // 默认state
    let defaultState = {
      searchList: [] // 搜索结果列表
    }
    
    // 使用handleActions处理多个actions ,这里通过action.payload获取传过来的数据
    const appReducer = handleActions(
      {
        [getAppInfoSucceed]: (state, action) => {
          return {
            ...state,
            appInfo: action.payload
          }
        },
        [getPostsSucceed]: (state, action) => {
          return {
            ...state,
            pageConfig: {
              page: action.payload.page,
              pageSize: action.payload.pageSize
            },
            listCollection: {
              posts: action.payload.list
            }
          }
        }
      },
      defaultState
    )
    
    export default appReducer
    

    5、redux/rootSaga.js
    接着,我们将所有的saga方法导入进来,并通过combineSagas方法进行组合

    import { combineSagas } from '../utils/sagaUtils'
    import { appWatcher } from './app/saga'
    
    export const rootSaga = combineSagas([appWatcher])
    
    
    
    这里的sagaUtils是一个工具函数,使用map遍历fork所有的sagas
    import { all, fork } from 'redux-saga/effects'
    
    export const combineSagas = sagas =>
      function* rootSaga(args) {
        try {
          yield all(sagas.map(saga => fork(saga, args)))
        } catch (err) {
          console.error(err)
        }
      }
    

    6、redux/index.js
    最后在index.js中,导入所有的rootSaga和reducer,使用 applyMiddleware 将 middleware 连接至 Store

    import { createStore, applyMiddleware, combineReducers } from 'redux'
    import createSagaMiddleware from 'redux-saga'
    import { rootSaga } from './rootSaga'
    // import rootReducer from './reducers'
    
    import appReducer from './app/reducers'
    
    const rootReducer = combineReducers({
      appState: appReducer
    })
    
    export function initializeStore(initialState) {
      // 创建一个 Saga middleware
      const sagaMiddleware = createSagaMiddleware()
    
      // 使用 applyMiddleware 将 middleware 连接至 Store
      const store = createStore(
        rootReducer,
        initialState,
        applyMiddleware(sagaMiddleware)
      )
    
      // 运行并监控各个action
      store.sagaTask = sagaMiddleware.run(rootSaga)
    
      return store
    }
    

    参考

  • 相关阅读:
    2.安装双系统linux+windows
    1.在虚拟机上安装linux系统
    python2升级python3(linux)并解决兼容问题
    selenium模拟登录_百度指数
    解决YUM下LoadedpluginsfastestmirrorDeterminingfastestmirrors 的问题
    yum源地址卸载、下载、安装
    Redis无法启动You may fix this problem by either reducing the size of the Redis heap with the --maxheap
    第二章 演化式架构师
    第一章 微服务
    第19章 未来的软件构架
  • 原文地址:https://www.cnblogs.com/fozero/p/12113937.html
Copyright © 2011-2022 走看看