Dekoratory w React.

0

Czesc, stosujecie dekoratory w aplikacjach reactowych ?

0

Co masz na myśli pisząc dekoratory? Jeśli ci chodzi o wzorzec projektowy dekoratora https://pl.wikipedia.org/wiki/Dekorator_(wzorzec_projektowy) to owszem, zdarza mi się pisać Higher Order Components, np.

function foo(Component) {
   return () => <Component foo="x" />
}

czyli w zasadzie funkcja foo jest takim dekoratorem (jeśli rozumieć dekorator jako wzorzec projektowy).

Jednak NIE korzystam z dekoratorów jako część języka (czyli nie korzystam z tej nowości @costam, tylko samemu opakowuję to w odpowiednie funkcje. Nie mam nic przeciwko notacji z małpą, po prostu nie dotarłem do tego jeszcze, nie wiem czy w ogóle jest to już w języku, z tej tablicy wynika, że nie ma wsparcia nigdzie dla tego: http://kangax.github.io/compat-table/esnext/ ).

0

Natywnego nie ma, ale po to sa transpilatory :)

0

Problem w tym, że dekoratory nie weszły jeszcze do języka (z tego co widzę, to są na stage 2 dopiero, czyli draft https://github.com/tc39/proposal-decorators )
lista stage'ów: https://tc39.github.io/process-document/

Ja osobiście wolę używać starego dobrego ES6, niż tych nowszych elementów języka, które są w fazie eksperymentalnej jeszcze.

2

@LukeJL
Odpowiem w poscie bo komentarze niewygodne dla kodu.

Z drugiej strony definicje dekoratora dotyczą zwykle klas, co niekoniecznie się będzie tłumaczyć 1:1 do programowania funkcyjnego.

W FP wzorzec dekoratora pojawia się tak samo, choć nie jest to jakiś specjalny koncept jak w OOP (dla którego warto by był tworzyć osobny syntax) - ot po prostu konkretny sposób składania funkcji. Założenia są dokładnie te same - stworzyć nowy byt rozszerzający funkcjonalność, implementujący ten sam interfejs (w przypadku funkcji typ funkcji jest "interfejsem"), tak by opakowaną funkcję / klasę / metodę można było użyć w miejscu nieopakowanej funkcji / klasy / metody bez zmian w kodzie.

Na przykładzie loggera:

a) osobny dekorator zwracjaacy funkcję o tym samym typie co funkcja pierwotna:

// original:
// type F = (number) => number
const square = a => a ** 2

const logger = fn => input => {
  console.log(input)
  const output = fn(input)
  console.log(output)
  
  return output;
}

// decorated:
// type F' = (number) => number
const squareWithLogging = logger(square)
 
square(7)
squareWithLogging(7)

a) dekorator za pomocą kompozycji (także ten sam typ dekorowanej funkcji co funkcji wynikowej):

// type F = (number) => number
const square = a => a ** 2

const log = a => {
  console.log(a)
  return a
}

// type F' = (number) => number
const squareWithLogging = a => log(square(log(a)))

square(7)
squareWithLogging(7)

Udekorowanej funkcji możesz teraz użyć wszędzie, gdzie była używana funkcja nieudekorowana:

const arr = [1, 2, 3]

const resultA = arr
  .filter(x => x % 2 !== 0)
  .map(square)
  .reduce((acc, x) => acc + x)

const resultB = arr
  .filter(x => x % 2 !== 0)
  .map(squareWithLogging)
  .reduce((acc, x) => acc + x)

console.log({
  resultA,
  resultB
})

Twój przykład nie spełnia wymagań (niezgodne typy):

// original:
// type F = (Props) => Component
const Hello = ({ name }) => (
  <p>Hello {name}</p>
)

const useMe = Component => () => <Component name="Maciek" />

// pseudo decorated:
// type F' = (void) => Component
const DecoratedHello = useMe(Hello) // oops, not the same type anymore

class App extends Component {
  render() {
    return (
      <div className="App">
        <Hello name="Maciek" />
        <DecoratedHello name="John"/> {/* <--- props lost in limbo ;) */}
      </div>
    );
  }
}

0 użytkowników online, w tym zalogowanych: 0, gości: 0