Last active
February 5, 2017 17:46
-
-
Save likwrk/29a19f9f6ff565616d414b05dc7ff0f2 to your computer and use it in GitHub Desktop.
rxjs flux implementation
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
// Flux implementation in RxJS | |
// https://github.com/ryardley/rxjs-as-redux | |
// http://rudiyardley.com/redux-single-line-of-code-rxjs/ | |
console.clear(); | |
const action$ = new Rx.Subject(); | |
const isObservable = obs => obs instanceof Rx.Observable; | |
const actionDispatcher = (func) => (...args) => | |
action$.next(func(...args)); | |
const createStore = (reducer, initState) => | |
action$ | |
.flatMap((action) => isObservable(action) ? action : Rx.Observable.from([action])) | |
.startWith(initState || reducer()) | |
.scan(appReducer).share(); | |
const changeName = actionDispatcher((payload) => ({ | |
type: 'NAME_CHANGED', | |
payload: payload | |
})); | |
const addTodo = actionDispatcher((payload) => ({ | |
type: 'ADD_TODO', | |
payload: payload | |
})); | |
const userReducer = (state = {name: 'Harry'}, action) => { | |
switch(action.type) { | |
case 'NAME_CHANGED': | |
// return new object with changed name. Do not chage original object | |
return Object.assign({}, state, {name: action.payload}); | |
default: | |
return state; | |
} | |
} | |
const todosReducer = (state = [], action) => { | |
switch(action.type) { | |
case 'ADD_TODO': | |
// return new array with appended todo. Do not change original array | |
return [...state, action.payload]; | |
default: | |
return state; | |
} | |
} | |
const appReducer = (state = {}, action = {}) => { | |
console.log(action) | |
return { | |
user: userReducer(state.user, action), | |
todos: todosReducer(state.todos, action) | |
} | |
} | |
// store handles whole app state | |
const store$ = createStore(appReducer, {user: {name: 'Alex'}, todos: ['afd', 'fff', 'ddd']}); | |
const handleClick = (e) => { | |
if (e) e.preventDefault(); | |
action$.next(addTodo('newTodo')) | |
} | |
const handleKeyup = (e) => { | |
action$.next(changeName(e.target.value)) | |
} | |
const getHtml = (state) => { | |
return `<p>${state.user.name}</p> | |
<ul>${state.todos.map(t => `<li>${t}</li>`).join('')}</ul>` | |
} | |
// subscribe to store chanes, and when store changed update html | |
// in angular pass this state to component | |
store$.subscribe(state => { | |
document.getElementById('content1').innerHTML = getHtml(state); | |
}) | |
store$.subscribe(state => { | |
document.getElementById('content2').innerHTML = getHtml(state); | |
}) | |
store$.subscribe(state => { | |
document.getElementById('content3').innerHTML = getHtml(state); | |
}) | |
store$.subscribe(state => { | |
document.getElementById('name').value = state.user.name; | |
}) | |
Rx.Observable.fromEvent(document.getElementById('name'), 'keyup') | |
.debounceTime(500) // do not update on every key up | |
.distinctUntilChanged() // update if only data changed | |
.subscribe(handleKeyup) | |
Rx.Observable.fromEvent(document.getElementById('button'), 'click') | |
.subscribe(handleClick) | |
action$.next(); // trigger store change to get render inital data; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment