React - użyteczność komponentów wyższego rzędu?

0

cześć, jestem w trakcie nauki Reacta, uczę się z książki w której jest przedstawiony taki kod:

import React from "react";

function ProFeature(FeatureComponent) {
  return function (props) {
    if (props.pro) {
      let { pro, ...childProps } = props;
      return <FeatureComponent {...childProps} />;
    } else {
      return (
        <h5 className="bg-danger text-white text-center">
          To jest mozliwosc tylko dla specow.
        </h5>
      );
    }
  };
}

export default ProFeature;

W app.js

const ProtectedMessage = ProFeature(Message);
<div className="col-3">
          <ProtectedMessage
            theme="primary"
            message="Wiadomosc chroniona"
            pro={true}
          />
        </div>

Trochę mi zajęło czasu aby zrozumieć na czym polega funkcjonalność takiego komponentu, bądź opakowania. Równie dobrze można zabezpieczyć renderowanie komponentu przez taki zapis kodu:

{user.isLoggedIn && <Message message="Wiadomosc chroniona" />}

Mam tu na myśli store, który przechowa wartość isLoggedIn. Chciałbym się zapytać: czy często są stosowane takie komponenty? ps. książka to React 16 - Adama Freemana

0

Unikam. Funkcje wyższego rzędu pociągają za sobą komplikacje niemal jak dziedziczenie.

https://solovyov.net/blog/2020/higher-order-functions/

0

Nie wiem jak w książce, bo nie miałem okazji jej przeczytać, ale dokumentacja (https://pl.reactjs.org/docs/higher-order-components.html) dokładnie opisuje czym są takie komponenty (HOC) i kiedy można je stosować.

Można powiedzieć, że jest to taki wzorzec dziedziczenia komponentów w Reactcie, który pozwala nam na zmodyfikowanie komponentu za pomocą parametrów.

import React, { useState, useEffect } from 'react';
import Page from '../components/Page.js';

function ProtectedHOC(PageComponent, role) {
  return function (props) {
    const [isAccess, isAccess] = useState(false);
    const [isLoading, setIsLoading] = useState(true);
    const [user, setUser] = useState({});

    useEffect(() => {
      fetch('https://localhost:8080/api/users/')
        .then((response) => response.responseJson())
        .then((json) => {
          setIsLoading(false);

          if (role.includes(json.user.role)) {
            setUser(json.user);
            setAcces(true);
          }
        })
    }, [])

    if (isLoading) {
      return (
        <div className="loading">
          Trwa ładowanie strony...
        </div>
      );
    }
    
    if (isAccess) {
      return (
        <div className="protected-page">
          <PageComponent user={user} role={role} {...props} />
        </div>
      );
    }

    return (
      <div className="error">
        <h1>Brak dostępu</h1>
        <p>Nie masz uprawnień do oglądania tej strony</p>
      </div>
    );
  };
}

const AdminPage = ProtectedHOC(Page, ['admin']);
const AdminSettingsPage = ProtectedHOC(Page, ['admin']);

const EditorPage = ProtectedHOC(Page, ['admin', 'editor']);

const UserPage = ProtectedHOC(User, ['user']);
const UserSettingsPage = ProtectedHOC(User, ['user']);

Co robi HOC:

  1. Na samym początku, gdy nie ma danych z API wyświetla stan ładowania
  2. Pobiera dane z API
  3. Sprawdza, czy rola użytkownika pasuje do roli, która została przekazana w parametrze
  4. Gdy rola się zgadza to przekazuje dane o użytkowniku do komponentu
  5. Jeśli rola się nie zgadza, to wyświetla komunikat o błędzie

W nowszych projektach coraz rzadziej się je spotyka, bo weszły przykładowo hooki, które umożliwiają zrobienie tego samego w prostszy sposób, ale warto je znać, bo czasami niektóre biblioteki udostępniają jedynie HOC'y i wypadałoby wiedzieć jak one działają.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.