This package has been deprecated

Author message:

with-hook has been replaced by with-hooks-support, which has a cleaner and more intuitive API. Consider using that package instead to add hooks support to React class components.

with-hook

0.2.9 • Public • Published

withHook

DEPRECATED: The with-hook package is deprecated.

Consider using the with-hooks-support package instead, which has a cleaner and more intuitive API for allowing hooks inside class components.


Unlock React Hooks inside class components.

class FancyInput extends React.Component {
  render() {
    // `useFormInput` returns an object with `value` and `onChange` attributes.
    const WithFormInput = withHook(useFormInput);
 
    return (
      <WithFormInput>
        {inputProps => <input {...inputProps} />}
      </WithFormInput>
    );
  }
}

Check out the Code Sandbox Demo!

Usage

npm install with-hook

Then import

import withHook from 'with-hook';

Introduction

React hooks (introduced in react@17.0.0-alpha) lets you use state and other React features without writing a class ie. in functional components. The result is cleaner, more readable code where the code for a single feature is colocated instead of being spread over several life-cycle methods.

Now that you have rewritten all your features as hooks, how do you use them in your legacy class components? Using the withHook higher order component, that's how!

Consider the following functional component:

function FunctionalComponent() {
  const [width, setWidth] = useState(window.innerWidth);
  const handleWindowResize = () => setWidth(window.innerWidth);
  useEffect(() => {
    window.addEventListener('resize', handleWindowResize);
    return () => window.removeEventListener('resize', handleWindowResize);
  });
 
  return <div>The window width is {width}</div>;
}

We can add the same hooks code to our class component:

class ClassComponent extends React.PureComponent {
  render() {
    const WithWindowWidth = withHook(() => {
      const [width, setWidth] = useState(window.innerWidth);
      const handleWindowResize = () => setWidth(window.innerWidth);
      useEffect(() => {
        window.addEventListener('resize', handleWindowResize);
        return () => window.removeEventListener('resize', handleWindowResize);
      });
 
      return width;
    });
 
    return (
      <WithWindowWidth>{width => <div>The window width is {width}</div>}</WithWindowWidth>
    );
  }
}

Now if we were to refactor all our hooks code into a custom hook

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);
  const handleWindowResize = () => setWidth(window.innerWidth);
  useEffect(() => {
    window.addEventListener('resize', handleWindowResize);
    return () => window.removeEventListener('resize', handleWindowResize);
  });
 
  return width;
}

We can write our components like so:

function FunctionalComponent() {
  const width = useWindowWidth();
 
  return <div>The window width is {width}</div>;
}
 
class ClassComponent extends React.PureComponent {
  render() {
    const WithWindowWidth = withHook(useWindowWidth);
 
    return (
      <WithWindowWidth>
        {width => <div>The window width is {width}</div>}
      </WithWindowWidth>
    );
  }
}

Special case: Hooks that don't return a value

Now, suppose you don't care about the return value for a hook. The child to the hook component can be a normal component instead of a render function.

class AwesomeTextarea extends React.Component {
  constructor(props) {
    super(props);
    this.textareaRef = React.createRef();
  }
 
  render() {
    const WithAutosizing = withHook(() => useAutosizingTextarea(this.textareaRef));
    return (
      <WithAutosizing>
        <textarea ref={this.textareaRef} />
      <WithAutosizing>
    );
  }
}

Awesome!

Package Sidebar

Install

npm i with-hook

Weekly Downloads

1

Version

0.2.9

License

MIT

Unpacked Size

12.3 kB

Total Files

10

Last publish

Collaborators

  • dibyo