Skip to content

Instantly share code, notes, and snippets.

@mdboop
Last active August 30, 2017 21:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdboop/7366da3bcd129d81bed79da52dea5096 to your computer and use it in GitHub Desktop.
Save mdboop/7366da3bcd129d81bed79da52dea5096 to your computer and use it in GitHub Desktop.
Functional null-check and code-branching with React
/**
* 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: 'joy@foo.com' },
{ subject: 'Call me when you can', body: null, sentBy: 'frederico@bar.com' },
{ subject: 'Will meet you @5 eom', body: '', sentBy: 'paul@boz.com' },
{ subject: 'Hey!', body: 'Let\'s grab lunch this week. When are you free?', sentBy: 'akhila@baz.com' }
];
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