Skip to content

Latest commit

 

History

History

either

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

either

either(testFn: props => boolean, option: props => value ) (target: props => value) => value

Either takes a test function which creates an HOC to take another function and will execute that function if the function passes. It also has an option to take a "left-hand" argument to execute instead if the test function fails. If no option was provided, the HOC will return a null.

  • Examples:
const GreenOrRedLight = either(props => props.batteryCharged === '100%', RedComponent)(GreenComponent)
return <ChargingDisplay>
				<GreenOrRedLight batteryCharged="88%" />
			<ChargingDisplay/>
// renders the RedComponent
const MaybeDisplayHelpChat = either(prop => props.loggedIn === false)(HelpChat)
return <MaybeDisplayHelpChat loggedIn /> // renders nothing

either is mainly inspired by recompose's branch function, with a goal to be more concise and streamlined, defaulting to a "maybe" render by returning null. Unlike branch - the either HOC does not apply a "right hand" argument to target - implying that it will only return the value of the target rather than renderComponent(target). A value comes back from the last execution, rather than one more HOC wrapper. To emphasize this difference in application, either has its "left-hand" and "right-hand" arguments reversed in comparison to branch. In either the "left" argument is the option for a failed test, and target is what is returned upon success.


either can be used with plain JS functions, not just React.
const SnitchOrKeepQuiet = either({ stayLoyal } => stayLoyal === true)(console.log)
const knowledge = SnitchOrStayQuiet({ stayLoyal: true, secrets: "Mob secrets" })
// null

Composition

A great advantage to using this "maybe-render" design pattern is to take the inline-conditionals out of your React components, and place the focus on Component composition.

Before:

const ComponentThatFetches = props => (
<div>
	{ !props.isDataFetched ? <LoadingSpinner /> }
	{props.isDataFetched && props.responseIsCorrupted && <ErrorMessage />}
	{props.isDataFetched && !props.responseIsCorrupted && <DataVisual />}
	{ props.isChatForumFetched ? <ChatForum /> : <LoadingSpinner />}
</div>)
// This is a giant jumble of conditional expressions

After:

const DataDisplay = either(props => !props.responseIsCorrupted, ErrorMessage)(DataVisual)

// Notice how this decorator function is decoupled from any target Component
const maybeLoadingScreen = either(props => props.isDataFetched, LoadingSpinner)

// Now we can apply a possible loading feedback to any component
const DataOrLoading = maybeLoadingScreen(DataDisplay)
const ChatDiscussion = maybeLoadingScreen(ChatForum)

// Our final top-level component becomes much more concise and clear in its declaration
const ComponentThatFetches = props => (
<div>
	<RenderDataOrLoading {...props} />
	<ChatForum responseFetched={props.isChatForumFetched} />
</div>
)