Closed bodhi closed 8 years ago
thanks for your implementation.
not sure it would work well in practice because here it assumes that the components holding state will never be unmounted. I think we could decide to temporarily hide the counter and the state should be kept (but it can be put in parent anyway, but it's a problem if parent is far up the tree)
Also think it's doable using a single Redux store
not sure it would work well in practice because here it assumes that the components holding state will never be unmounted.
Very good point! In the Redux project I'm working on, we tend to (probably understating!) use only stateless functions, so I often forget about component mounting/unmounting.
(copied from
README.md
)Scalable frontend, with React/Redux/Whatever-react-based-library-you-want
This feels a little bit like cheating, but given the problem definition, especially the emphasis on decoupling, I thought that perhaps there's no need to force each component to be implemented with Redux, Redux + redux-thunk, Redux + Sagas, Mobx, whatever.
Instead, each component is rendered as an "opaque" React component. They are opaque in that the integration team has no idea how each other team has implemented their component (or even really care), they just have to implement a defined business-level interface (exposed as a React component).
One drawback of this approach is that you no longer have a single state atom, but if you're really serious about decoupling, this is a plus, right? ;) Any state sharing between components needs to become explicit, but not so convenient...
One interesting thing about this approach (that may also be true of the other approaches, I haven't studied them closely) is that it could easily support having N counters and N buttons. The integration team could wire them up however they like.
Interfaces
NewGif
type component must take anonNewGif
prop, that is a function of type() => void
.Button
component must have a functionbuttonState
, of type() => bool
, that returns the button's state ("active" =>true
).Counter
component must have a functionincrement
of typebool => void
, that will increment the counter. The interface does not specify whether theCounter
implements the business rule, as this is an internal detail that should be hidden from the user of the component.Implementation
NewGif
is implemented as a Redux app that will, when the button is pressed:NEW_GIF
into its own store (which will cause theconnect
edGif
component to update with the new gif URL.onNewGif
to signal that the gif was changed.GifPair
andPairPair
are basically dumb components that pass theironNewGif
props straight through to the childNewGif
.Button
is a plain React component that stores its button's state in the React component state. It exposes the button state via a function on the classbuttonState
.Counter
is also implemented as a Redux app that has a single Redux action:INC
, that hasbuttonState
as the payload. The ability to trigger a dispatch of this action is exposed to users of the component via theincrement
function on the component. The business rule is implemented in the reducer, withcounter
coming from the state, andbuttonState
coming from the action.App
wires the components together by:onNewGif
prop of any Gif-like component (NewGif
,GifPair
,PairPair
) that gets the button state via the ref, and trigges the counter increment (again via a ref), passing along the button state.