Created
February 8, 2017 12:42
-
-
Save pedronauck/fa168f832bea48576771e1a5da539870 to your computer and use it in GitHub Desktop.
Todo Duck example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { List, fromJS } from 'immutable'; | |
import { createSelector } from 'reselect'; | |
import { createAction, handleActions } from 'redux-actions'; | |
import { takeLatest, takeEvery, take, fork, put, select } from 'redux-saga/effects'; | |
import * as todos from 'ducks/entities/todos'; | |
/** | |
* Constants | |
**/ | |
const BASE_ACTION = 'modules/my-module'; | |
const FETCH_RESOURCES = `${BASE_ACTION}/FETCH_RESOURCES`; | |
const TOGGLE_ACTIVE = `${BASE_ACTION}/TOGGLE_ACTIVE`; | |
const SELECT_TODO = `${BASE_ACTION}/SELECT_TODO`; | |
/** | |
* Reducer | |
**/ | |
const initialState = Map({ | |
error: false, | |
isLoading: false, | |
showingActive: false, | |
selectedTodo: null | |
}); | |
const handler = { | |
[FETCH_RESOURCES]: (state, { payload }) => | |
state | |
.set('isLoading', true) | |
.set('error', false), | |
[TOGGLE_ACTIVE]: (state, { payload }) => | |
state | |
.set('showingActive', !state.get('showingActive')) | |
[SELECT_TODO]: (state, { payload }) => | |
state | |
.set('selectedTodo', payload), | |
[`${todos.actions.fetchResponse}`]: (state, { payload, error }) => | |
state | |
.set('isLoading', false) | |
.set('error', error ? payload.message : null) | |
}; | |
export default handleAction(handler, initialState); | |
/** | |
* Selectors | |
**/ | |
export const selectedTodoSelector = (state) => | |
state.getIn(['modules', 'my-modules', 'selectedTodo']); | |
export const showingActiveSelector = (state) => | |
state.getIn(['modules', 'my-modules', 'showingActive']); | |
export const getTodosToShow = createSelector( | |
[todos.todosSelector, todos.getActiveTodos, showingActiveSelector], | |
(todos, activeTodos, showingActiveSelector) => showingActiveSelector ? activeTodos : todos | |
); | |
export const getSelectedTodo = createSelector( | |
[todos.todosSelector, selectedTodoSelector], | |
(todos, id) => todos.find(todo => todo.get('id') === id) | |
); | |
/** | |
* Sagas and Actions | |
**/ | |
export const actions = { | |
fetchResources: createAction(FETCH_RESOURCES), | |
selectTodo: createAction(SELECT_TODO), | |
toggleActive: createAction(TOGGLE_ACTIVE) | |
}; | |
function* fetchResources() { | |
yield take(`${todos.actions.fetchResponse}`); | |
const allTodos = yield select(todos.todosSelector); | |
const firstTodo = todos.first(); | |
yield put(actions.selectTodo(firstTodo.get('id'))); | |
} | |
export function* sagas() { | |
yield [ | |
fork(todos.fetchTodos), | |
yield takeLatest(actions.fetchResources, fetchResources) | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { fromJS } from 'immutable'; | |
import { createSelector } from 'reselect'; | |
import { createAction, handleActions } from 'redux-actions'; | |
import { put, call } from 'redux-saga/effects'; | |
import { fetch } from 'utils'; | |
/** | |
* Constants | |
**/ | |
const BASE_ACTION = 'ducks/entities/todos'; | |
const FETCH_RESPONSE = `${BASE_ACTION}/FETCH_RESPONSE`; | |
/** | |
* Reducer | |
**/ | |
const initialState = List(); | |
const handles = { | |
[FETCH_RESPONSE]: (state, { payload, error }) => !error ? List(payload) : state | |
}; | |
export default handleActions(handler, initialState); | |
/** | |
* Selectors | |
**/ | |
export const todosSelector = (state) => state.get('todos'); | |
export const getActiveTodos = createSelector( | |
[todosSelector], | |
(todos) => todos.filter(todo => todo.get('active')) | |
); | |
/** | |
* Api | |
**/ | |
export const api = { | |
fetchTodos: () => fetch.get('/todos'), | |
fetchTodo: (id) => fetch.get(`/todos/${id}`) | |
}; | |
/** | |
* Sagas and Actions | |
**/ | |
export const actions = { | |
fetchResponse: createAction(FETCH_RESPONSE) | |
}; | |
export function* fetchTodos() { | |
try { | |
const { data } = yield call(api.fetchTodos); | |
yield put(actions.fetchResponse(data)); | |
} catch(error) { | |
yield put(actions.fetchResponse(new Error(error.message))); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment