Skip to content

Instantly share code, notes, and snippets.

View tomkis's full-sized avatar

Tomáš Weiss tomkis

View GitHub Profile
// incorrect, does not work for the exact midnight
var today = moment(),
yesterday = moment().subtract(1, 'days');
// correct but ugly
var today = moment(),
yesterday = today.clone().subtract(1, 'days');
// pretty but unable to write with momentjs because instance is not immutable
var today = moment(),
@tomkis
tomkis / gist:6783b848401b6a9b351a
Created April 30, 2015 18:11
Flux - business logic in stores

This is a reaction to https://twitter.com/tomkisw/status/593822104589578240

I would personally prefer to keep business logic in one place. And this place ideally should be the store. I have always been fan of having stores completely synchronous and to move any communication with the API to action creators. It works pretty nice as long as you don't need to parametrize your API calls, once you get to this point, then some funky stuff in your code may actually happen. The state of your application should be encapsulated inside your stores and the only component that can directly access it, is a controller-view.

It's absolutely valid to keep your API calls in action creators as long as you don't do any business logic in there (no branching, no store dependency, no state manipulation).

You have also mentioned you might even need state from multiple stores. Technically, there is nothing wrong about duplicating state across multiple stores (e.g. listening to the same action from multiple stores), it's something

@tomkis
tomkis / routable_hoc.jsx
Created October 11, 2015 18:42
Routable high order component.
export default routable('/absolute/route/foo', props => <span>Foo</span>);
// Current Redux way
const view = props => (
<div>
<button onClick={props.dispatch({type: 'FOO'})}>FooBar</button>
<button onClick={props.dispatch({type: 'BAR'})}>FooBar</button>
<button onClick={props.dispatch({type: 'BAZ'})}>Baz</button>
</div>
);
const store = createStore(rootReducer);
import api from './path/to/api'
import { take } from 'redux-saga'
function* watchSave() {
while(true) {
const { data } = yield take('SAVE_DATA');
// Just naive example that callbacks do not propagate yield*
yield* data
.forEach(function*(record) {
@tomkis
tomkis / redux-elm-routing.js
Created June 2, 2016 15:36
redux-elm with react-router
///
/// <---- rootView.js
///
import { view } from 'redux-elm';
import buildRouting from './buildRouting';
export default view(({ history }) => buildRouting(history));
@tomkis
tomkis / reducers-as-generators.js
Created November 20, 2015 16:18
what if your reducers were generators?
// You can defer the side-effect execution in middlewares
const sideEffect = appState => dispatch => localStorage.setItem('counter', appState);
function plainOldReducer(appState) {
return appState + 1;
}
// Composition simply work
function nestedReducer*(appState, action) {
if (action === FOO) {
@tomkis
tomkis / main.js
Created September 2, 2016 11:32
redux-observable epic hot reloading
// main.js
import { Subject } from 'rxjs';
import { createStore, compose, applyMiddleware } from 'redux';
import pingPongReducer from './pingPongReducer';
import pingPongEpic from './pingPongEpic';
const buildEpicSubscriber = () => {
let subscription = null;
@tomkis
tomkis / react-router-redux.js
Last active January 11, 2017 03:08
react-router-redux with react-router 4.x
import React, { Component } from 'react';
import Match from 'react-router/Match';
import { connect } from 'react-redux';
import * as ActionTypes from '../constants/actionTypes';
import buildActionCreators from '../helpers/buildActionCreators';
const EMPTY_PROPS = {};
const createMountableComponent = (Cmp, routeId) => connect(
@tomkis
tomkis / rxjs-saga.js
Last active May 13, 2018 14:01
rxjs-saga.js
import { createStore, applyMiddleware } from 'redux';
import { Observable, Subject } from 'rxjs';
const api = (url, fail) => {
console.log(`Loading API ${url}`);
return new Promise((res, rej) => setTimeout(() => fail ? rej(`data-${url}`) : res('SUCCESS'), 1000));
};
const customSaga = iterable =>
iterable