Skip to content

Instantly share code, notes, and snippets.

@likwrk
Last active February 5, 2017 17:46
Show Gist options
  • Save likwrk/29a19f9f6ff565616d414b05dc7ff0f2 to your computer and use it in GitHub Desktop.
Save likwrk/29a19f9f6ff565616d414b05dc7ff0f2 to your computer and use it in GitHub Desktop.
rxjs flux implementation
// 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