Last active
April 15, 2022 15:03
-
-
Save negamaxi/9e2736e5b58b23f232f33b1430ed556e to your computer and use it in GitHub Desktop.
Separate component logic from view using React Hooks
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
// Outside props goes here first to be transformed according to Component's logic | |
export const useComponentState = props => { | |
const { disabled } = props; | |
const [loggedIn, setLoggedIn] = React.useState(initialLoggedIn); | |
const onLogInButtonClick = () => { | |
if (!disabled) { | |
setLoggedIn(true); | |
} | |
}; | |
const onLogOutButtonClick = () => { | |
if (!disabled) { | |
setLoggedIn(false); | |
} | |
}; | |
const hasLogInButton = !loggedIn; | |
const hasLogOutButton = loggedIn; | |
return { | |
hasLogInButton, | |
hasLogOutButton, | |
onLogInButtonClick, | |
onLogOutButtonClick | |
}; | |
}; |
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
// Props recieved from useComponentState hook | |
export const ComponentView = (props) => { | |
const { | |
hasLogInButton, | |
hasLogOutButton, | |
handleLogInButtonClick, | |
handleLogOutButtonClick | |
} = props; | |
return ( | |
<header> | |
{ | |
hasLogInButton && ( | |
<LogInButton onClick={handleLogInButtonClick}/> | |
) | |
} | |
{ | |
hasLogOutButton && ( | |
<LogOutButton onClick={handleLogOutButtonClick}/> | |
) | |
} | |
</header> | |
) | |
} |
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
// Use withHook HOC to connect Component's state to Component's view | |
import { withHook } from './withHook' | |
import { useComponentState } from './useComponentState' | |
import { ComponentView } from './ComponentView' | |
export const Component = withHook(useComponentState, ComponentView); |
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
// Component usage example | |
import { Component } from './Component' | |
const Parent = () => ( | |
<Component disabled /> | |
) |
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
// A simple function that do the trick | |
export const withHook = ( | |
hook, view | |
) => { | |
return (props) => { | |
return view(hook(props)); | |
}; | |
}; | |
// typescript | |
type TReturnType<T1> = (props: T1) => React.ReactNode; | |
export const withHook = <T1, T2>( | |
hook: (p: T1) => T2, | |
view: (p: T2) => React.ReactNode | |
): TReturnType<T1> => { | |
return props => { | |
return view(hook(props)); | |
}; | |
}; | |
// @flow | |
type TReturnType<T1> = (props: T1) => React.Node; | |
export const withHook = <T1: {}, T2: {}>( | |
hook: (p: T1) => T2, | |
view: (p: T2) => React.Node | |
): TReturnType<T1> => { | |
return props => { | |
return view(hook(props)); | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment