Компоненты высшего порядка в Hyperstack

#javascript #ruby #reactjs #hyperstack

#javascript #ruby #reactjs #hyperstack

Вопрос:

Существует частый случай использования библиотек javascript, когда вы хотите украсить свои компоненты компонентами более высокого порядка.

Например, библиотека material-ui включает компонент более высокого порядка для стилизации withStyles .

В javascript вы бы сделали

 import { withStyles } from '@material-ui/core';

const styles = {
  example: {
    padding: 8
  }
}
const SomeComponent = ({classes}) => <div className={classes.example}>I'm a component</div>;

export default withStyles(SomeComponent);
  

Как вы можете достичь того же в Hyperstack?

Ответ №1:

Во-первых, похоже, что есть проблема, которую вам нужно исправить. Это будет исправлено в следующем выпуске point: просто добавьте этот метод в свой Hypercomponent базовый класс ( app/hyperstack/components/hypercomponent.rb )

 def self.to_n
  Hyperstack::Internal::Component::ReactWrapper.create_native_react_class(self)
end
  

Теперь, если у вас есть следующие стили:

 MY_STYLES = {root: {backgroundColor: 'red'}}
  

и компонент, который вы хотите стилизовать:

 class StyleTest < HyperComponent
  param :some_param
  param :classes
  render do
    DIV(class: classes[:root]) { some_param }
  end
end
  

Вы можете сделать это следующим образом:

 class StyledTest1 < HyperComponent
  imports `Mui.withStyles(#{MY_STYLES.to_n})(#{StyleTest.to_n})`
end
  

Что происходит, так это то, что мы переходим к JS, используя обратные ссылки и вызывая Mui.with_styles напрямую и передавая его MY_STYLES (точно так же, как в примере MUI doc). to_n Преобразуется из хэша Ruby в объект JS. (При передаче параметров компонентам это происходит автоматически, но не так при простых вызовах функций.)

Затем мы вызываем результирующий HOC с помощью нашего StyleTest класса (также вызываем to_n для преобразования из класса Ruby в простой класс JS).

Наконец, мы импортируем его обратно в класс компонентов Hyperstack.

Это немного больше работы, чем мне хотелось бы, поэтому мы можем просто добавить удобный вспомогательный метод в наш HyperComponent класс:

 class HyperComponent
  include Hyperstack::Component
  include Hyperstack::State::Observable
  param_accessor_style :accessors  # this is now the prefered param style

  # patch for issue: https://github.com/hyperstack-org/hyperstack/issues/153
  def self.to_n
    Hyperstack::Internal::Component::ReactWrapper.create_native_react_class(self)
  end

  # our helper macro:
  def self.add_styles(style, opts = {})
    imports `Mui.withStyles(#{style.to_n}, #{opts.to_n})(#{superclass.to_n})`
  end
end
  

Теперь мы можем добавлять стили, подобные этому:

 class StyledTest2 < StyleTest
  add_styles MY_STYLE
end
  

и теперь у нас есть новый класс компонентов с нашим стилем в нем.

Например:

 class App < HyperComponent

  render do
    DIV do
      StyledTest1(some_param: 'test 1')
      StyledTest2(some_param: 'test 2')
    end
  end
end
  

Комментарии:

1. Я не имею в виду разъяснять некоторыми комментариями. В большинстве документов используются средства доступа в стиле param, которые выглядят следующим образом @MyParam . В будущем это будет устаревшим, потому что это слишком уродливо. Вы можете получить новый синтаксис, подобный тому, который я использовал, добавив его param_accessor_style :accessors в HyperComponent базовый класс. Просто не хотел, чтобы вы запутались!