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
}

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM