Sharing behaviour between React components

React 0.13 introduced using plain Javascript classes to create components, 0.14 introduced "stateless functional components" as another method of defining them. Neither of these have an in-built method for behaviour sharing such as we had with the mixins option passed to createClass. So now we get to review mixins as a pattern for behaviour sharing and, if necessary, come up with something better. If they're not all bad, we'll need to figure out how to, or even if we can, add them to the two new component definition options.

The problem

Dan Abromov's medium article from Mar 2015 makes the case for avoiding mixins.

For me (paraphrasing in the extreme), the key problems exposed are:

  • mixins can unintentionally hide / distribute the source of behaviour
View alternative.hs
module Main where
import Control.Applicative
import Data.Monoid
fizz n
| n `mod` 3 == 0 = Just "Fizz"
| otherwise = Nothing
buzz n
View recursive-foldable.hs
{-# LANGUAGE DeriveFoldable #-}
module Main where
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Foldable
data Object a
= Value a
View pythagoreans.hs
{-# LANGUAGE LambdaCase #-}
module Main
( main
) where
import Control.Monad (guard)
import Control.Monad.Trans.State (StateT (StateT), evalStateT)
import Data.List (unfoldr)
import Data.Maybe (listToMaybe)
View weekdays-until.hs
module Main where
import Data.Time
import Data.Time.Clock
import Data.Time.Format
import Data.Time.Calendar
import Data.Maybe
import System.Environment
import Text.ParserCombinators.ReadP
import Data.Char
View biuld-error.log
cabal: Entering directory '/run/user/1000/cabal-tmp-20052/ghcjs-0.2.1'
[1 of 1] Compiling Main ( /run/user/1000/cabal-tmp-20052/ghcjs-0.2.1/dist/dist-sandbox-6a8a5e5a/setup/setup.hs, /run/user/1000/cabal-tmp-20052/ghcjs-0.2.1/dist/dist-sandbox-6a8a5e5a/setup/Main.o )
Linking /run/user/1000/cabal-tmp-20052/ghcjs-0.2.1/dist/dist-sandbox-6a8a5e5a/setup/setup ...
Configuring ghcjs-0.2.1...
Flags chosen: no-wrapper-install=False, network-uri=True, compiler-only=False
Dependency Cabal == using Cabal-
Dependency HTTP ==4000.3.9: using HTTP-4000.3.9
Dependency aeson == using aeson-
Dependency array == using array-
Dependency attoparsec == using attoparsec-
View collection-compare.js
function allInCollection (collection) {
return function (subCollection) {
return subCollection.every(function (subItem) {
return collection.some(function (item) {
return ===;

Modules example

A module which represents part of a Reaat app could export an array of routes and a reducer.

export {default as routes} from './routes'
export {default as reducer} from './store/reducer'

The top level application can take these exports and collect them together into the root routes def and the root reducer.

View Tree.hs
module Data.Tree where
import Data.Monoid
data KeyValue k v = KeyValue k v
instance (Show k, Show v) => Show (KeyValue k v) where
show (KeyValue k v) = "(" ++ show k ++ ", " ++ show v ++ ")"
instance (Eq k) => Eq (KeyValue k v) where
View one-req.js
export const finishRegistration = ({ id, attributes }) => (dispatch) => {
payload: { id }
return finish({ id, attributes }).then(({