Polski

Odkryj moc wzorca Render Props w React. Dowiedz się, jak promuje on ponowne użycie kodu, kompozycję komponentów i rozdzielenie odpowiedzialności, umożliwiając elastyczne i łatwe w utrzymaniu aplikacje dla międzynarodowej publiczności.

Wzorzec Render Props w React: Elastyczna logika komponentów dla globalnej publiczności

W stale ewoluującym krajobrazie rozwoju front-end, szczególnie w ekosystemie React, wzorce architektoniczne odgrywają kluczową rolę w budowaniu skalowalnych, łatwych w utrzymaniu i wielokrotnego użytku komponentów. Wśród tych wzorców, wzorzec Render Props wyróżnia się jako potężna technika udostępniania kodu i logiki między komponentami React. Ten post na blogu ma na celu zapewnienie kompleksowego zrozumienia wzorca Render Props, jego zalet, przypadków użycia oraz tego, jak przyczynia się on do budowania solidnych i adaptowalnych aplikacji dla globalnej publiczności.

Czym są Render Props?

Render Prop to prosta technika udostępniania kodu między komponentami React za pomocą propa, którego wartością jest funkcja. Zasadniczo, komponent z render prop przyjmuje funkcję, która zwraca element React i wywołuje tę funkcję, aby coś wyrenderować. Komponent nie decyduje bezpośrednio o tym, co ma renderować; deleguje tę decyzję do funkcji render prop, zapewniając jej dostęp do swojego wewnętrznego stanu i logiki.

Rozważmy ten podstawowy przykład:


class DataProvider extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null };
  }

  componentDidMount() {
    // Simulate fetching data
    setTimeout(() => {
      this.setState({ data: 'Some data from an API' });
    }, 1000);
  }

  render() {
    return this.props.render(this.state.data);
  }
}

function MyComponent() {
  return (
     (
        
{data ?

Data: {data}

:

Loading...

}
)} /> ); }

W tym przykładzie DataProvider pobiera dane i przekazuje je do funkcji render prop dostarczonej przez MyComponent. MyComponent następnie używa tych danych do renderowania swojej zawartości.

Dlaczego warto używać Render Props?

Wzorzec Render Props oferuje kilka kluczowych zalet:

Realne przypadki użycia i międzynarodowe przykłady

Wzorzec Render Props jest cenny w różnych scenariuszach. Oto kilka typowych przypadków użycia z przykładami, które uwzględniają globalną publiczność:

1. Śledzenie myszy

Wyobraź sobie, że chcesz śledzić pozycję myszy na stronie internetowej. Używając Render Prop, możesz utworzyć komponent MouseTracker, który dostarcza współrzędne myszy swoim dzieciom.


class MouseTracker extends React.Component {
  constructor(props) {
    super(props);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove = event => {
    this.setState({ x: event.clientX, y: event.clientY });
  };

  render() {
    return (
      
{this.props.render(this.state)}
); } } function MyComponent() { return ( (

The mouse position is ({x}, {y})

)} /> ); }

Można to łatwo dostosować do aplikacji zinternacjonalizowanych. Na przykład wyobraź sobie aplikację do rysowania używaną przez artystów w Japonii. Współrzędne myszy mogłyby być używane do kontrolowania pociągnięć pędzla:


 (
    
  )}
/>

2. Pobieranie danych z API

Pobieranie danych z API jest częstym zadaniem w tworzeniu stron internetowych. Komponent Render Prop może obsługiwać logikę pobierania danych i dostarczać dane swoim dzieciom.


class APIFetcher extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null, loading: true, error: null };
  }

  async componentDidMount() {
    try {
      const response = await fetch(this.props.url);
      const data = await response.json();
      this.setState({ data: data, loading: false });
    } catch (error) {
      this.setState({ error: error, loading: false });
    }
  }

  render() {
    return this.props.render(this.state);
  }
}

function MyComponent() {
  return (
     {
        if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; return
{JSON.stringify(data, null, 2)}
; }} /> ); }

Jest to szczególnie przydatne podczas pracy z zlokalizowanymi danymi. Na przykład wyobraź sobie wyświetlanie kursów wymiany walut dla użytkowników w różnych regionach:


 {
    if (loading) return 

Loading exchange rates...

; if (error) return

Error fetching exchange rates.

; return (
    {Object.entries(data.rates).map(([currency, rate]) => (
  • {currency}: {rate}
  • ))}
); }} />

3. Obsługa formularzy

Zarządzanie stanem formularza i walidacją może być skomplikowane. Komponent Render Prop może hermetyzować logikę formularza i dostarczać stan formularza i handlery swoim dzieciom.


class FormHandler extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '', error: null };
  }

  handleChange = event => {
    this.setState({ value: event.target.value });
  };

  handleSubmit = event => {
    event.preventDefault();
    if (this.state.value.length < 5) {
      this.setState({ error: 'Value must be at least 5 characters long.' });
      return;
    }
    this.setState({ error: null });
    this.props.onSubmit(this.state.value);
  };

  render() {
    return this.props.render({
      value: this.state.value,
      handleChange: this.handleChange,
      handleSubmit: this.handleSubmit,
      error: this.state.error
    });
  }
}

function MyComponent() {
  return (
     alert(`Submitted value: ${value}`)}
      render={({ value, handleChange, handleSubmit, error }) => (
        
{error &&

{error}

}
)} /> ); }

Rozważ dostosowanie reguł walidacji formularza, aby uwzględnić międzynarodowe formaty adresów. Komponent `FormHandler` może pozostać ogólny, podczas gdy render prop definiuje konkretną logikę walidacji i UI dla różnych regionów:


 sendAddressToServer(address)}
  render={({ value, handleChange, handleSubmit, error }) => (
    
{/* Fields for address, adapting to regional formats */} {error &&

{error}

}
)} />

4. Flagi funkcji i testy A/B

Render Props można również używać do zarządzania flagami funkcji i przeprowadzania testów A/B. Komponent Render Prop może określić, która wersja funkcji ma być renderowana na podstawie bieżącego użytkownika lub losowo wygenerowanej flagi.


class FeatureFlag extends React.Component {
  constructor(props) {
    super(props);
    this.state = { enabled: Math.random() < this.props.probability };
  }

  render() {
    return this.props.render(this.state.enabled);
  }
}

function MyComponent() {
  return (
     {
        if (enabled) {
          return 

New Feature!

; } else { return

Old Feature

; } }} /> ); }

Podczas testowania A/B dla globalnej publiczności ważne jest segmentowanie użytkowników na podstawie języka, regionu lub innych danych demograficznych. Komponent `FeatureFlag` można zmodyfikować, aby uwzględniał te czynniki przy określaniu, która wersja funkcji ma być wyświetlana:


 {
    return isEnabled ?  : ;
  }}
/>

Alternatywy dla Render Props: Komponenty wyższego rzędu (HOC) i Hooki

Chociaż Render Props są potężnym wzorcem, istnieją alternatywne podejścia, które mogą osiągnąć podobne rezultaty. Dwie popularne alternatywy to komponenty wyższego rzędu (HOC) i Hooki.

Komponenty wyższego rzędu (HOC)

Komponent wyższego rzędu (HOC) to funkcja, która przyjmuje komponent jako argument i zwraca nowy, ulepszony komponent. HOC są powszechnie używane do dodawania funkcjonalności lub logiki do istniejących komponentów.

Na przykład HOC withMouse mógłby zapewnić funkcjonalność śledzenia myszy komponentowi:


function withMouse(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = { x: 0, y: 0 };
    }

    handleMouseMove = event => {
      this.setState({ x: event.clientX, y: event.clientY });
    };

    render() {
      return (
        
); } }; } function MyComponent(props) { return (

The mouse position is ({props.mouse.x}, {props.mouse.y})

); } const EnhancedComponent = withMouse(MyComponent);

Chociaż HOC oferują ponowne użycie kodu, mogą prowadzić do kolizji nazw prop i utrudniać kompozycję komponentów, zjawisko znane jako "wrapper hell".

Hooki

React Hooki, wprowadzone w React 16.8, zapewniają bardziej bezpośredni i ekspresyjny sposób ponownego wykorzystania logiki stanowej między komponentami. Hooki pozwalają "zahaczyć się" w funkcje stanu i cyklu życia React z komponentów funkcyjnych.

Używając hooka useMousePosition, funkcjonalność śledzenia myszy można zaimplementować w następujący sposób:


import { useState, useEffect } from 'react';

function useMousePosition() {
  const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    function handleMouseMove(event) {
      setMousePosition({ x: event.clientX, y: event.clientY });
    }

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, []);

  return mousePosition;
}

function MyComponent() {
  const mousePosition = useMousePosition();
  return (
    

The mouse position is ({mousePosition.x}, {mousePosition.y})

); }

Hooki oferują czystszy i bardziej zwięzły sposób ponownego wykorzystania logiki stanowej w porównaniu z Render Props i HOC. Promują również lepszą czytelność i łatwość konserwacji kodu.

Render Props vs. Hooki: Wybór odpowiedniego narzędzia

Decyzja między Render Props a Hookami zależy od konkretnych wymagań projektu i osobistych preferencji. Oto podsumowanie ich kluczowych różnic:

Najlepsze praktyki dotyczące używania Render Props

Aby efektywnie korzystać ze wzorca Render Props, rozważ następujące najlepsze praktyki:

Wniosek

Wzorzec Render Props jest cenną techniką budowania elastycznych i wielokrotnego użytku komponentów React. Hermetyzując logikę i udostępniając ją komponentom za pomocą render prop, możesz promować ponowne użycie kodu, kompozycję komponentów i rozdzielenie odpowiedzialności. Chociaż Hooki oferują nowocześniejszą i często prostszą alternatywę, Render Props pozostają potężnym narzędziem w arsenale programisty React, szczególnie podczas pracy z legacy code lub scenariuszami wymagającymi precyzyjnej kontroli nad procesem renderowania.

Rozumiejąc korzyści i najlepsze praktyki wzorca Render Props, możesz budować solidne i adaptowalne aplikacje, które zaspokajają potrzeby zróżnicowanej globalnej publiczności, zapewniając spójne i angażujące doświadczenie użytkownika w różnych regionach i kulturach. Kluczem jest wybór odpowiedniego wzorca – Render Props, HOC lub Hooki – w oparciu o konkretne potrzeby projektu i wiedzę zespołu. Pamiętaj, aby zawsze priorytetowo traktować czytelność kodu, łatwość konserwacji i wydajność przy podejmowaniu decyzji architektonicznych.