How to use useEffect in Preact?
Asked Answered
B

2

5

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.

Blackstone answered 12/6, 2019 at 6:22 Comment(2)
Hooks were released as part of React 16.8. Preact hooks are in beta. github.com/preactjs/preact/pull/1302.Nival
The preact site says its is comparable to react 15.x but useffect looks like its react 16 reactjs.org/docs/hooks-effect.htmlGromyko
W
4

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';

Wilek answered 12/6, 2020 at 0:51 Comment(0)
N
11

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 [email protected]

Usage,

import { useState } from 'preact/hooks'

export function Demo(props) {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(c => c+1)}>{count}</button>
}
Nival answered 12/6, 2019 at 6:32 Comment(0)
W
4

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';

Wilek answered 12/6, 2020 at 0:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.