react-with-hoc
Version:
Work with React and HOCs (Higher-Order Components)
172 lines (126 loc) • 4.64 kB
Markdown
# react-with-hoc <!-- omit in toc -->
<a href="https://leobastiani.github.io/react-with-hoc/">
<img src="https://raw.githubusercontent.com/leobastiani/react-with-hoc/main/.github/logo/logo.png" />
</a>
**Type safe** and **Zero-cost** React library to work with higher-order component (HOC)
[](https://leobastiani.github.io/react-with-hoc/)
[](https://www.npmjs.com/package/react-with-hoc)
[](https://github.com/leobastiani/react-with-hoc/actions/workflows/test.yml)

[](https://bundlephobia.com/package/react-with-hoc)
[](https://www.npmjs.com/package/react-with-hoc?activeTab=dependencies)
[](https://github.com/leobastiani/react-with-hoc/blob/main/LICENSE)
- [Getting Started](#getting-started)
- [Usage example](#usage-example)
- [Hello World](#hello-world)
- [Example with react-query](#example-with-react-query)
- [Clock](#clock)
## Getting Started
[Read the docs](https://leobastiani.github.io/react-with-hoc/)
Install with npm
```bash
npm install react-with-hoc
```
Or install with yarn
```bash
yarn add react-with-hoc
```
## Usage example
### Hello World
```tsx
import { withDefault, withOverride, withHocs } from "react-with-hoc";
export const Hello = (() => {
function Hello({ name }: { name: string }) {
return <div>Hello {name}!</div>;
}
return withHocs([withDefault({ name: "World" })])(Hello);
})();
// <Hello /> is equivalent to <div>Hello World!</div>
// <Hello name="You" /> is equivalent to <div>Hello You!</div>
export const HelloYou = withOverride("name", "You")(Hello);
// <HelloYou /> is equivalent to <div>Hello You!</div>
// <HelloYou name="..." /> is a typescript error ❌
```
### Example with react-query
Lets suppose you have the following code and then you need a query inside your App component
```tsx
const queryClient = new QueryClient();
function App() {
// Oops... ❌
// This is an error because App is not wrapped by QueryClientProvider
const query = useQuery({...});
return (
<QueryClientProvider client={queryClient}>
<>...</>
</QueryClientProvider>
);
}
export default App;
```
Using `react-with-hoc`, you can easily fix this with:
```tsx
import {withWrapper, withOverride} from "react-with-hoc";
const queryClient = new QueryClient();
function App() {
// ✅
const query = useQuery({...});
return (
<>...</>
);
}
export default withWrapper(
withOverride({ client: queryClient })(QueryClientProvider)
)(App);
// for didactic purpose, the following code could also be applied
// const MyQueryClientProvider = withOverride({ client: queryClient })(QueryClientProvider)
// export default withWrapper(MyQueryClientProvider)(App);
```
Using [IIFE](https://developer.mozilla.org/pt-BR/docs/Glossary/IIFE)
```tsx
import { withWrapper, withOverride, withHocs } from "react-with-hoc";
const queryClient = new QueryClient();
const App = (() => {
function App() {
// ✅
const query = useQuery({...});
return <>...</>;
}
return withHocs([
withWrapper(withOverride({ client: queryClient })(QueryClientProvider)),
])(App);
})();
export default App;
```
### Clock
- [Demo](https://leobastiani.github.io/react-with-hoc/example/)
- [Source](https://github.com/leobastiani/react-with-hoc/tree/main/example/src/App.tsx)
Check out an entire project with react-with-hoc, see the [demo](https://leobastiani.github.io/react-with-hoc/example/) and try to imagine creating a reusable component with the same flexibility
Take a look on how simple it's the final result
```tsx
const RedHour = withOverride("color", "red")(HourPointer);
const Square = withStyle({
borderRadius: 0,
})(ClockCircle);
function App(): JSX.Element {
return (
<>
<div>
<h1>The default clock</h1>
<Clock />
</div>
<div>
<h1>#1 Variant: without minute marks</h1>
<Clock MinuteMarks={null} />
</div>
<div>
<h1>#2 With a red hour pointer</h1>
<Clock HourPointer={(): typeof RedHour => RedHour} />
</div>
<div>
<h1>#3 Inside a square</h1>
<Clock Circle={(): typeof Square => Square} />
</div>
</>
);
}
```