2017-07-08 238 views
0

我正在清理從一開始就錯誤的減速機設置。我使用redux docothe ducks pattern來設置它。設計/組合減速機減速機

我想單獨/分我的狀態像doco suggests

{ 
    domainData1 : {}, 
    domainData2 : {}, 
    appState1 : {}, 
    appState2 : {}, 
    ui : { 
     uiState1 : {}, 
     uiState2 : {}, 
    } 
} 

在我來說,我有一些專輯,目錄和照片,我正在努力進行管理。國家應該是這個樣子:

{ 
    //domainData 
    albums : {...}, 
    catalogs : {...}, 
    photos : {...}, 

    //appState 
    selectedAlbum : {...}, 

    //uiState 
    ui : { 
     loading : {}, 
     uiState2 : {}, 
    } 
} 

我已經把屬於專輯的所有代碼在一個文件,其中的動作,動作的創造者,recuders和API位於 類似的目錄和照片。 然後我將reducer與combineReducers組合在一個單獨的文件中。下面

代碼...

我的問題是什麼?當我做的東西在專輯我會希望所有的域數據進入狀態的專輯分支。但我不希望UI和應用程序狀態的東西進入專輯分支 - 這應該進入應用程序和UI狀態分支。這是我的設置不可能的,例如當加載相冊時,我在「相冊」減速器中設置加載標誌,這是fedRed的combineReducer,結果是加載狀態成爲相冊分支的一部分狀態...

相冊模塊:

import { createRequest, responseHandler, notAuthorized } from './apiUtils'; 
import { List, Map, fromJS } from 'immutable'; 

//actions 
const REQUEST_ALBUMS = 'REQUEST_ALBUMS'; 
const FETCH_ALBUMS_SUCCESS = 'FETCH_ALBUMS_SUCCESS'; 
const FETCH_ALBUM_SUCCESS = 'FETCH_ALBUM_SUCCESS'; 
const REQUEST_ALBUM = 'REQUEST_ALBUM'; 
const CREATE_ALBUM = 'CREATE_ALBUM'; 
const CREATE_ALBUM_SUCCESS = 'CREATE_ALBUM_SUCCESS'; 
const UPDATE_ALBUM = 'UPDATE_ALBUM'; 
const UPDATE_ALBUM_SUCCESS = 'UPDATE_ALBUM_SUCCESS'; 

// Reducer 
var init = Map(fromJS({ 
    albums: [], 
    album: [], 
    loading: false, 
})); 

var newState = null; 

export function reducer(state=init, action={}) { 
    switch (action.type) { 

    case FETCH_ALBUMS_SUCCESS: { 
     newState = state 
     .set('albums', fromJS(action.payload.albums)) 
     .set('loading', false); 
     return newState; 
    } 

    case REQUEST_ALBUMS: { 
     return state.set('loading', true); 
    } 

    case FETCH_ALBUM_SUCCESS: { 
     newState = state 
     .set('album', fromJS(action.payload.album)) 
     .set('loading', false); 
     return newState; 
    } 

    case REQUEST_ALBUM: { 
     return state.set('loading', true); 
    } 

    case CREATE_ALBUM: { 
     return state.set('loading', true); 
    } 

    case CREATE_ALBUM_SUCCESS: { 
     newState = state 
     .set('album', fromJS(action.payload.album)) 
     .set('loading', false); 
     return newState; 
    } 

    case UPDATE_ALBUM: { 
     return state.set('loading', true); 
    } 

    case UPDATE_ALBUM_SUCCESS: { 
     newState = state 
     .set('album', fromJS(action.payload.album)) 
     .set('loading', false); 
     return newState; 
    } 
    } 
    return state; 
} 

// Action Creators 
export function getAlbumsPending(response) { 
    return { 
    type: REQUEST_ALBUMS, 
    }; 
} 

export function getAlbumsSuccess(response) { 
    return { 
    type: FETCH_ALBUMS_SUCCESS, 
    payload: response, 
    }; 
} 

export function getAlbumPending(response) { 
    return { 
    type: REQUEST_ALBUM, 
    }; 
} 

export function getAlbumSuccess(response) { 
    return { 
    type: FETCH_ALBUM_SUCCESS, 
    payload: response, 
    }; 
} 

function createAlbumPending(response) { 
    return { 
    type: CREATE_ALBUM, 
    }; 
} 

function createAlbumSuccess(response) { 
    return { 
    type: CREATE_ALBUM_SUCCESS, 
    payload: response, 
    }; 
} 

export function updateAlbumPending(response) { 
    return { 
    type: UPDATE_ALBUM, 
    }; 
} 

export function updateAlbumSuccess(response) { 
    return { 
    type: UPDATE_ALBUM_SUCCESS, 
    payload: response, 
    }; 
} 

//API 

export function fetchAlbums() { 
    //API url 
    const url = '/api/albums.json'; 

    //make the call 
    return dispatch => { 

    dispatch(getAlbumsPending()); 

    fetch(createRequest('GET', url, null)) 
    .then(response => responseHandler(response)) 
    .then(data => dispatch(getAlbumsSuccess(data))) 
    .catch(error => console.log('request failed', error)); 
    }; 
} 

export function fetchAlbum(id) { 
    //url 
    var url = '/api/albums/'.concat(id); 

    return dispatch => { 
    dispatch(getAlbumPending()); 

    fetch(createRequest('GET', url, null)) 
    .then(response => responseHandler(response)) 
    .then(data => dispatch(getAlbumSuccess({ album: data }))) 
    .catch(error => console.log('request failed', error)); 
    }; 
} 

export function createAlbum(params) { 
    //API url 
    const url = '/api/albums/'; 

    return dispatch => { 

    dispatch(createAlbumPending()); 

    fetch(createRequest('POST', url, params)) 
    .then(response => responseHandler(response)) 
    .then(data => dispatch(createAlbumSuccess({ album: data }))) 
    .catch(error => console.log('request failed', error)); 
    }; 
} 

export function updateAlbum(params) { 
    //API url 
    var url = '/api/albums/'.concat(params.id); 

    //make the call 
    return dispatch => { 

    dispatch(updateAlbumPending()); 

    fetch(createRequest('PUT', url, params)) 
    .then(response => responseHandler(response)) 
    .then(data => dispatch(updateAlbumSuccess({ album: data }))) 
    .catch(error => console.log('request failed', error)); 
    }; 
} 

CombineRecucer:

import { combineReducers } from 'redux'; 
import { reducer as albumReducer } from '../actions/album'; 
import { reducer as catalogReducer } from '../actions/catalog'; 

export default combineReducers({ 
    albums: albumReducer, // <- loading flag ends up here 
    catalogs: catalogReducer, 
    loading: // I want loading flag here 
}); 

很抱歉的長期職位 - 沒有土豆

+0

您必須在'loading'減速器中添加'case UPDATE_ALBUM:'東西。您可以從其他鴨文件中導入動作類型。專輯reducer只負責更新自己的狀態片。多個減速器可以監聽相同的動作類型,並對其自己的片進行一些更改。 –

+0

OMG ...那麼簡單..我完全錯過了redux的天才...... @HåkenLid提出了一個答案,所以我可以信任你 – martin

+0

當然。我已經添加了答案。 –

回答

1

你只需動這種邏輯到加載減速responsib對於該州的這一部分。

// ducks/Loading.js 

import { 
    REQUEST_ALBUM, 
    CREATE_ALBUM, 
    CREATE_ALBUM_SUCCESS 
} from 'ducks/Albums' 
// remember to also export from the Albums duck. 

export const reducer = (state, action) => { 
    switch (action.type) { 
    case REQUEST_ALBUM: 
    case CREATE_ALBUM: 
     return state.set('loading', true) 

    case CREATE_ALBUM_SUCCESS: 
     return state.set('loading', false) 
    } 
} 

您可以從其他鴨文件中導入動作類型。 Albums簡化器只負責更新自己的狀態片。

多個縮減器可以偵聽相同的動作類型,並對其自己的片進行一些更改。所以CREATE_ALBUM_SUCCESS也可以觸發相冊減速器的一些變化。

你也可以通過其他方式實現它。例如,通過在動作的meta字段中使用密鑰。這避免了必須進行大量的導入和導出操作,因爲減速器不必知道操作的類型。

// loading reducer 
export const reducer = (state = false, action) => 
    (action.meta && action.meta.loading !== undefined) 
    ? action.meta.loading 
    : state 


// action creator 
export const updateAlbumPending =() => ({ 
    type: UPDATE_ALBUM, 
    meta: { 
    loading: true 
    } 
})