How to use useEffect in Preact?

Viewed 5643

I came across posts where people mention useEffect and even give some great examples, but I cannot find any real documentation. Also I grepped node_modules/preact dir and there is no mention of useEffect in the entire code base. Is this a separate module? Or I got the wrong version of preact (8.4.2)? Please explain and give a complete working example.

2 Answers

Hooks were released as part of React 16.8. Preact hooks are in beta as of version 10. You can get access to them by updating Preact to the latest beta with npm install preact@10.0.0-beta.2

Usage,

import { useState } from 'preact/hooks'

export function Demo(props) {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(c => c+1)}>{count}</button>
}

useEffect is primarily about accessing the Lifecycle Methods in a FunctionalComponent.

Preact ClassComponents have direct access to the Lifecycle methods, but FunctionalComponents do not.

Therefore, useEffect() acts as all the Lifecycle Methods rolled into one.

For example: (Full example using Preact/Typescript)

In a ClassComponent you can load data via the ComponentDidMount lifecycle method:

import { h, Component } from 'preact';
import * as style from './style.scss';
import { get } from '../../../utils/ajax';
import { ExampleDataObject } from '../types';

interface ComponentNameProps {
  id: number;
}

interface ComponentNameState {
  data: ExampleDataObject;
}

export class ComponentName extends Component<ComponentNameProps, ComponentNameState> {
  public render ({ id }: ComponentNameProps, { data }: ComponentNameState) {
     return (
        <div class={style.container}>
          {JSON.stringify(data)}
        </div>
     );
  }
  public componentDidMount(): void {
     get(`/getData?id=${id}`).then((d) => {
        this.setState({ data: d });
     });
  }
}

In a FunctionalComponent, the same effect can be achieved thus:

import { h, FunctionalComponent } from 'preact';
import * as style from './style.scss';
import { useState, useEffect } from 'preact/hooks';
import { get } from '../../../utils/ajax';
import { ExampleDataObject } from '../types';

interface ExampleProps {
  id: number;
}

export const Example: FunctionalComponent<ExampleProps> = ({id}) => {
const [data, setData] = useState<ExampleDataObject | undefined>;
useEffect(() => {
  get<ExampleDataObject>(`/getData?id=${id}`)
     .then((d) => {
        setData(d);
     });
}, [id]);

     return (
        <div class={style.ExampleWrapper}>
          {data !== undefined && (
             JSON.stringify(data)
          )};
        </div>
     );
}

Reminder: (for those using VSCode - which should be everyone-in-the-know):
VSCode will often do the import lines for you (i.e. using the Quick Fix helper) - but it often gets the import line wrong for useState / useEffect (it will add /src to the end, which doesn't work). So remember to double-check imports for these two.

WRONG:
import { useState, useEffect } from 'preact/hooks/src';

CORRECT:
import { useState, useEffect } from 'preact/hooks';

Related