useImperativeHandle



useImperativeHandle

av Ole Petter den 15. mars 2023

Sist oppdatert: 17 mars, 2023 kl 15:06

useImperativeHandle er en React hook som er nyttig i flere tilfeller hvor man vil forhindre unødvendig ekstra rendering av en komponent. I dette eksempelet brukes den til å vise og skjule en modal, og ved hjelp av React.forwardRef kan man lage funksjoner som kan sendes tilbake til en foreldrekomponent.

Foreldrekomponenten kan også sende verdier og funksjoner fra en under-komponent til en annen, så lenge den også bruker forwardRef. React context eller Redux brukes ofte til å håndtere slike situasjoner med state management, men i tilfeller som den under er det gjerne litt i overkant mye arbeid hvis man har en liten applikasjon.

  useImperativeHandle(
    ref,
    () => {
      return {
        openModal: () => setShow(true),
        closeModal: () => onClose(),
        isOpen: () => show,
      };
    },
    []
  );

Modalen blir eksportert wrappet med React.forwardRef:

export default forwardRef(Modal);

Bruk av useImperativeHandle gjør at man slipper å sende props frem og tilbake mellom komponenter, og sette opp en egen ekstra useState() funksjon i foreldrekomponenten.

Contents

Kode

App.tsx

import { useRef } from 'react';

import './App.css';
import Modal, { ModalProps } from './components/Modal';

function App() {
  const modalRef = useRef<ModalProps>(null);

  function openModal() {
    modalRef?.current?.openModal();
  }

  return (
    <div className="App">
      <h2>useImperativeHandle</h2>
      <button onClick={openModal}>Open modal</button>
      <Modal ref={modalRef} />
    </div>
  );
}

export default App;

Modal.tsx

import { forwardRef, useImperativeHandle, useState } from 'react';

export type ModalProps = {
  openModal: () => void;
  closeModal: () => void;
  isOpen: () => boolean;
};

function Modal(props: any, ref: any) {
  const [show, setShow] = useState(false);

  function onClose() {
    return setShow(false);
  }

  useImperativeHandle(
    ref,
    () => {
      return {
        openModal: () => setShow(true),
        closeModal: () => onClose(),
        isOpen: () => show,
      };
    },
    []
  );

  return (
    <div>
      {show && (
        <div
          className="modal-background"
          style={{
            top: 0,
            left: 0,
            height: '100%',
            width: '100%',
            position: 'fixed',
            backgroundColor: 'rgba(0, 0, 0, 0.4)',
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
          }}
        >
          <div
            className="modal"
            style={{
              height: '50%',
              width: '50%',

              justifyContent: 'center',
              backgroundColor: 'white',
            }}
          >
            <h2>Modal</h2>
            <button onClick={onClose}>Close</button>
          </div>
        </div>
      )}
    </div>
  );
}
export default forwardRef(Modal);

https://stackblitz.com/edit/vitejs-vite-3uz6mc?file=src/components/Modal.tsx

Legg igjen en kommentar