Last active
August 30, 2017 21:29
-
-
Save mdboop/7366da3bcd129d81bed79da52dea5096 to your computer and use it in GitHub Desktop.
Functional null-check and code-branching with React
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is something I threw together as a quick test. | |
* It's a contrived example because you'd likely just have one component for message and include something like: | |
* <p>{message.body || 'No message.'}</p> | |
* | |
* However, when I'm writing components, I often have to handle different UI treatments depending on the data. | |
* It's the same overall component, same logical chunk of UI, but it might take on three different forms, and | |
* those differences may have drastically different markup. Those situations make it easy start writing a lot | |
* of imperative code, and I always feel dissatisfied when I have to include if statements in my render functions. | |
* | |
* So, take a look at Messages, my first hack at a completely declarative bit of React. | |
* Feedback, thoughts, and miscellany all welcome. You can find me at @deanboop on twitter. | |
*/ | |
/* | |
* Either type and fromNullable helper from Brian Lonsdorf's excellent new egghead.io series. | |
* watch them here: https://egghead.io/lessons/javascript-linear-data-flow-with-container-style-types-box | |
*/ | |
const Right = x => ({ | |
chain: f => f(x), | |
map: f => Right(f(x)), | |
fold: (f, g) => g(x), | |
inspect: () => `Right(${x})` | |
}); | |
const Left = (x) => ({ | |
chain: (f) => Left(x), | |
map: (f) => Left(x), | |
fold: (f, g) => f(x), | |
inspect: () => `Left(${x})` | |
}); | |
const fromNullable = x => | |
x != null ? Right(x) : Left(null); | |
const messages = [ | |
{ subject: 'Your guitar', body: 'You forgot it at my house', sentBy: '[email protected]' }, | |
{ subject: 'Call me when you can', body: null, sentBy: '[email protected]' }, | |
{ subject: 'Will meet you @5 eom', body: '', sentBy: '[email protected]' }, | |
{ subject: 'Hey!', body: 'Let\'s grab lunch this week. When are you free?', sentBy: '[email protected]' } | |
]; | |
const ShortMessage = ({ message }) => ( | |
<div className="message"> | |
<h2>{message.subject}</h2> | |
<p><i>No message body.</i></p> | |
<p>from {message.sentBy}</p> | |
</div> | |
); | |
const LongMessage = ({ message }) => ( | |
<div className="message"> | |
<h2>{message.subject}</h2> | |
<p>{message.body}</p> | |
<p>{message.sentBy}</p> | |
</div> | |
); | |
// This is the bit to pay attention to. | |
const Message =({ message }) => fromNullable(message.body) | |
.fold(() => <ShortMessage message={message} />, | |
() => <LongMessage message={message} />); | |
const App = ({ messages }) => ( | |
<main> | |
<h1>messages</h1> | |
<section> | |
{messages.map((m, i) => <Message key={i} message={m} />)} | |
</section> | |
</main> | |
); | |
ReactDOM.render(<App messages={messages} />, document.getElementById('root')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment