There are times, when writing a large scale React application in which one component needs to send a message to another component that it is not a direct descendent or ancestor of, a cousin component, if you will. Two examples that spring to mind are:
- Needing to apply focus to a particular DOM node, which requires a ref to the actual DOM node.
- Needing to make some AJAX call, e.g. submitting a form, using information the receiving component has in its props.
Luckily, if you are writing a large enough React application, you are probably already using some sort of global state management, such as Redux. That’s great, so you have a common state that both components can read from and write to, but how does that help you pass a message? That’s where the world of international espionage comes in…
Draw the curtain and take a seat, Mr. Bond.
To quote Wikipedia:
A dead drop or dead letter box is a method of espionage tradecraft used to pass items or information between two individuals (e.g., a case officer and agent, or two agents) using a secret location, thus not requiring them to meet directly and thereby maintaining operational security. The method stands in contrast to the live drop, so-called because two persons meet to exchange items or information.
You already see where this is going, don’t you? The sending component needs to dispatch an action that will set some slice of the state that the receiving component is listening to. The flow goes like this:
- User interacts with Sender
- Sender dispatches an action to modifiy
trueor to any value that it wants to pass with the message.
- Receiver has
mapStateToPropswith a selector for
state.deaddrop, and thus gets rerendered with a new prop.
- Receiver initiates whatever action is required.
It is important to note here that the flow does not need to begin with a user interaction. With the rise of asynchronous middleware like
redux-observable, the ability to trigger any code on a component anywhere is very useful.
I briefly considered writing a
redux-dead-drop library, even going so far as “designing” a logo, with its own higher order reducer to enable this functionality on any reducer and a HOC to
connect any component the dead drop location on the reducer, and even have it call an instance method on its wrapped component. I'm still reasonably certain that it would be possible to write, but the design pattern is so simple that it takes hardly any effort to implement it on any existing reducer, so I rejected abstraction for abstraction's sake.
If you would like to try and implement such a library, help yourself to the name and logo.
As in the world of covert government agents, is important that the Receiver component clear out the dead drop once the message has been received.
I have used this pattern in my
redux-form library to enable the triggering of a form submission via the dispatch of an action. This allows the form component to know about how it needs to be submitted and validated, but also allows any actor in the entire application to trigger the submission.
This post will self destruct in 5…. 4…. 3….