All Projects → jul-sh → hook-into-props

jul-sh / hook-into-props

Licence: MIT License
Tiny HoC to use React hooks with class components.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to hook-into-props

Use Url State
Lift a React component's state into the url
Stars: ✭ 154 (+250%)
Mutual labels:  hooks, higher-order-component
Flagged
Feature Flags for React made easy with hooks, HOC and Render Props
Stars: ✭ 97 (+120.45%)
Mutual labels:  hooks, higher-order-component
Formik
Build forms in React, without the tears 😭
Stars: ✭ 29,047 (+65915.91%)
Mutual labels:  hooks, higher-order-component
React Nprogress
⌛️ A React primitive for building slim progress bars.
Stars: ✭ 173 (+293.18%)
Mutual labels:  hooks, higher-order-component
react-usemiddleware
React >=16.7 hook, allowing to use standard Redux middleware with useReducer
Stars: ✭ 19 (-56.82%)
Mutual labels:  hooks
click-outside-hook
A simple react hook to detect click or touch events outside an element.
Stars: ✭ 29 (-34.09%)
Mutual labels:  hooks
react-europe-2019
Slides and demo app from my keynote
Stars: ✭ 29 (-34.09%)
Mutual labels:  hooks
react-daterange-picker
A react date range picker to using @material-ui. Live Demo: https://flippingbitss.github.io/react-daterange-picker/
Stars: ✭ 85 (+93.18%)
Mutual labels:  hooks
hulks
Olist custom linting hooks 💚 👽
Stars: ✭ 25 (-43.18%)
Mutual labels:  hooks
atomic-state
A decentralized state management library for React
Stars: ✭ 54 (+22.73%)
Mutual labels:  hooks
micro-observables
A simple Observable library that can be used for easy state management in React applications.
Stars: ✭ 78 (+77.27%)
Mutual labels:  hooks
dothub
Stop managing your github config like a mere human
Stars: ✭ 14 (-68.18%)
Mutual labels:  hooks
jitm
JITM is an automated tool to bypass the JIT Hooking protection on a .NET sample.
Stars: ✭ 27 (-38.64%)
Mutual labels:  hooks
react-smart-app
Preconfiguration React + Ant Design + State Management
Stars: ✭ 13 (-70.45%)
Mutual labels:  hooks
state inspector
State change & method call logger. A debugging tool for instance variables and method calls.
Stars: ✭ 24 (-45.45%)
Mutual labels:  hooks
Perky
Perky a beautiful animated app concept built with lots of love in React Native.
Stars: ✭ 37 (-15.91%)
Mutual labels:  hooks
use-table-tools
React Hooks for building kickass react table components
Stars: ✭ 18 (-59.09%)
Mutual labels:  hooks
zoov
Use 🐻 Zustand with Module-like api
Stars: ✭ 24 (-45.45%)
Mutual labels:  hooks
crook
Simple hook management tool made with PHP
Stars: ✭ 60 (+36.36%)
Mutual labels:  hooks
learn-react-typescript
Learning React contents with TypeScript (Hooks, Redux)
Stars: ✭ 15 (-65.91%)
Mutual labels:  hooks

🚢 hook-into-props

Introduction

import React from 'react'
import hookIntoProps from 'hook-into-props'

class DisplayWindowSize extends React.Component {
  render() {
    return this.props.windowSize
  }
}

const useHooks = () => ({ windowSize: useWindowSize() })

export default hookIntoProps(useHooks)(DisplayWindowSize)

Installation

You can install it via npm i hook-into-props. (200 bytes + 1kb dependencies. See bundle-phobia)

Alternatively you can copy the source code, it's only a few lines. If you don't feel like adding any abstractions at all, check out without-abstractions.

Examples

Using props with hooks

import React from 'react'
import hookIntoProps from 'hook-into-props'

class SearchResults extends React.Component {
  render() {
    this.props.isLoading ? 'loading' : this.props.searchResults
  }
}

const useHooks = props => {
  const [isLoading, searchResults] = useFetch(
    `https://foo.com/?search=${props.searchTerm}`
  )

  return { isLoading, searchResults }
}

export default hookIntoProps(useHooks)(SearchResults)

Using multiple hooks

import React from 'react'
import hookIntoProps from 'hook-into-props'
import { ReferralCode, TimezoneOffset, FeatureList } from '~/contexts'

class UserForm extends React.Component {
  componentDidMount() {
    const { referralCode, timezoneOffset, featureList } = this.props
    // ...
  }
  render() {
    // ...
  }
}

const useHooks = () => ({
  referralCode: useContext(ReferralCode),
  timezoneOffset: useContext(TimezoneOffset),
  featureList: useContext(FeatureList)
})

export default hookIntoProps(useHooks)(UserForm)

Exporting Higher-Order-Components

export const withWindowSize = hookIntoProps(() => ({
  windowSize: useWindowSize()
}))

Under the hood

That's the (simplified) source code:

function hookIntoProps(useHooks) {
  return function(Component) {
    return function HooksProvider(props) {
      return <Component {...props} {...useHooks(props)} />
    }
  }
}

(The hook calls in useHooks are only executed when useHooks is called inside of HooksProvider. At that point they are called within a function component, where we can use hooks. The results of our hook calls are passed as props)

Alternatives

Without abstractions

To avoid any helpers at all, we could inline a functional component in the export statement.

import React from 'react'

class DisplayWindowSize extends React.Component {
  render() {
    return this.props.isLoading ? 'loading' : this.props.searchResults
  }
}

export default function HooksProvider(props) {
  const [isLoading, searchResults] = useFetch(
    `https://foo.com/?search=${props.searchTerm}`
  )

  return (
    <DisplayWindowSize
      {...props}
      isLoading={isLoading}
      searchResults={searchResults}
    />
  )
}

This can work very well for simple cases. It lays out the logic in a verbose manner.

There's some caveats to this though. First, the export must be a named function declaration, as else you end up with an odd React tree of Unkown components. Secondly, with more complexity, this can become harder to read. It becomes more difficult to see at a glance which component is really being exported. Also, you'll have to remember to manually spread props every time.

Render-props

We could also create a simple Component that allows us to consume hooks through render-props:

import React from 'react'

const HookProvider = ({ children, useHooks }) => children(useHooks())

class DisplayWindowSize extends React.Component {
  render() {
    return (
      <HookProvider useHooks={() => useWindowSize()}>
        {windowSize => <span>{windowSize}</span>}
      </HookProvider>
    )
  }
}

This looks clean, but we won't have access to the hook result in our other class methods. This can make it poor choice for supporting existing class components.

Rewriting your class as a function component

You could also refactor your class component and directly use hooks inside your new function component. However, refactoring existing classes isn't always an option.

Being able to use hooks with your old code can be convenient. It actually allows you to refactor existing higher order components to hooks without breaking support for your existing class components.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].