News for hackers. Stuff that matters.
Re:Build Yourself a Redux by fny on Friday May 05, 2017 @01:55PM (#14275409)
I never understood why a lot of this was never handled with metaprogramming. I feel like it might have something to do with Redux using constants and imports as a type safety hack, but all the ceremony drives me nuts.

First we enumerate our actions as constants...

    const ADD_TODO = 'ADD_TODO'
Then we need to create an "action creator" somewhere:

    import { ADD_TODO } from '../actionTypes'

    function addTodo(text) {
      return {
        type: ADD_TODO,
        text
      }
    }
Then we need to import that action and dispatch it when we need it...

    import addTodo from './actions'

    dispatch(addTodo(text))
Now even the same nonsense for reducers...
Re:Build Yourself a Redux by jamesisaac on Friday May 05, 2017 @03:42PM (#14276249)
I'd highly recommend using a type system like Flow to enumerate the shape of possible actions the store should support. This brings numerous advantages:

1. You can use strings for action types, no more need to import constants.

2. No need for action creators for simple actions, you can just create the action object inline and Flow will validate its shape.

3. You can be sure that reducers are unpacking properties that actually exist from the actions.

In other words, your example could simply be:

    // types.js
    type Action =
      | { type: 'ADD_TODO', text: string }

    // TodoList.js
    dispatch({ type: 'ADD_TODO', text })
...and Flow would confirm at 'compile time' that it matches the contract dispatch expects.

This approach has scaled up extremely well for me and no longer feels verbose.

Re:Build Yourself a Redux by nathan_f77 on Friday May 05, 2017 @05:36PM (#14277006)
I agree with that. When I first started with Redux and Flow, I was just following all the examples and made sure I used action creators for everything, even if there was no payload. Now I'm feeling more confident with Flux, and I recently realized that no, I don't need "action creators" for everything. That's silly. It's OK to just dispatch an object using your action constant directly.

And then I found myself writing action creators on purpose, not because I saw it in some tutorial, but because it actually does remove some duplication.

This was also missing from my education for a long time: https://github.com/acdlite/flux-standard-action#actions

I had no idea why I was using a "payload" key, instead of just putting all the values in the top-level object. But this convention makes a lot of sense now.

Re:Build Yourself a Redux by acemarke on Friday May 05, 2017 @02:26PM (#14275665)
And most of that came from Flux to begin with (as seen in https://facebook.github.io/react/blog/2014/07/30/flux-action... ). There's also a lot of interesting parallels with the Win32 WndProc functions, as discussed in https://bitquabit.com/post/the-more-things-change/ and https://bitquabit.com/post/the-more-things-change/ .

That said, you are absolutely encouraged to abstract over that process as much as you want! For example, the https://github.com/acdlite/redux-actions library will generate both the action constants and the action creators for you, and there's many more similar utilities.

Re:Build Yourself a Redux by acemarke on Saturday May 06, 2017 @11:57AM (#14280814)
Whoops, just noticed the bad copy-and-paste. Meant to link to the HN discussion for that article: https://news.ycombinator.com/item?id=10381015 .
Re:Build Yourself a Redux by stevejohnson on Friday May 05, 2017 @02:00PM (#14275463)
Speaking as someone working in a large Redux codebase, I agree with you 100%. The amount of boilerplate required to do almost anything is staggering.
Re:Build Yourself a Redux by jdeal on Friday May 05, 2017 @02:29PM (#14275684)
Personally, I find that when boilerplate gets out of control, you can do one of two things, probably in this order:

1. Write helpers. 2. Write middleware.

The first is zero magic, and allows you to opt-in to abstractions as needed. The latter is more powerful and can remove pretty much any boilerplate, but you have to be careful about introducing too much magic.

Redux isn't much different than any other code you might write. If you prematurely abstract, you could create a leaky abstraction, and you'll have to unroll the whole thing. If you don't abstract at all, and copy-pasta everything, you're also going to have a bad time.

Re:Build Yourself a Redux by acemarke on Friday May 05, 2017 @02:23PM (#14275640)
Dan Abramov has said that the Redux docs were written in a deliberately verbose style to get across the ideas, and he didn't really expect people to strictly imitate that style. There's a wide variety of approaches and utilities you can use to abstract things as much as you'd like - that's entirely up to you.
Re:Build Yourself a Redux by antoaravinth on Saturday May 06, 2017 @01:05PM (#14281196)
As a beginner in Redux, can you tell me about the other ways to handle these boilerplate?
Re:Build Yourself a Redux by acemarke on Monday May 08, 2017 @08:13PM (#14296722)
A few possible options:

- Put all the action types, action types, and reducers for a given portion of the application into one file. This is known as the "ducks" structure, per https://github.com/erikras/ducks-modular-redux .

- Use a utility library like https://github.com/acdlite/redux-actions to generate action types and action creators for you

- Write middleware to manage common logic for your application such as API calls

- Skip writing action creators and declaring action constants, and just have components do `this.props.dispatch({type : "SOME_ACTION"})`.

I don't recommend the last approach, but it's _totally_ up to you, especially because what you regard as "too much boilerplate" is going to be a personal opinion. One person's "too much boilerplate" is another person's "explicit and easy to trace through the system".

Re:Build Yourself a Redux by chucksmash on Friday May 05, 2017 @02:36PM (#14275741)
I usually handle this via text editor macros when I'm starting off

Start with

actionNames.txt

  ADD_TODO
  REMOVE_TODO
Cat that file to actionTypes.js and actions.js. In actionTypes.js, expand:

<line> to:

  export const <line> = "<line>"
And in actions.js, expand <line> to something like:

  export const (camelcase-string <line>) = () => {
    return {
      type: types.<line>,
    };
  };
Also instead of importing actions and actionTypes individually, I'll generally do:

  import * as actions from './actions';
  import * as types from './actionTypes';
  dispatch(actions.addTodo(...));
Re:Build Yourself a Redux by danielearwicker on Saturday May 06, 2017 @02:53PM (#14281671)
I developed a kind of meta programming pattern and supporting library, based on Redux, called Immuto, to get absolute and complete static typing (via TypeScript) and minimal boilerplate, also referentiality and modularity (cursors that accepted actions). It was fun, but ultimately pointless, as it was never as straightforward as using the automatic observable approach that I'd learned from Knockout.js. Then I heard about MobX (which is the same ideas from KO but better implemented and without any quirky UI templating thrown in) and so now I used that.

Also I use my json-mobx library to get serialisation and undo/redo. Example: https://github.com/danielearwicker/baltar