Skip to content

Instantly share code, notes, and snippets.

@negamaxi
Last active April 15, 2022 15:03
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save negamaxi/9e2736e5b58b23f232f33b1430ed556e to your computer and use it in GitHub Desktop.
Save negamaxi/9e2736e5b58b23f232f33b1430ed556e to your computer and use it in GitHub Desktop.
Separate component logic from view using React Hooks
// 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
};
};
// 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>
)
}
// 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);
// Component usage example
import { Component } from './Component'
const Parent = () => (
<Component disabled />
)
// 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