reactrb/reactrb

View on GitHub
lib/react/component.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'react/ext/string'
require 'react/ext/hash'
require 'active_support/core_ext/class/attribute'
require 'react/callbacks'
require 'react/rendering_context'
require 'hyper-store'
require 'react/state_wrapper'
require 'react/component/api'
require 'react/component/class_methods'
require 'react/component/props_wrapper'
require 'native'

module Hyperloop
  class Component
    module Mixin
      def self.included(base)
        base.include(Store::Mixin)
        base.include(React::Component::API)
        base.include(React::Component::Callbacks)
        base.include(React::Component::Tags)
        base.include(React::Component::DslInstanceMethods)
        base.include(React::Component::ShouldComponentUpdate)
        base.class_eval do
          class_attribute :initial_state
          define_callback :before_mount
          define_callback :after_mount
          define_callback :before_receive_props
          define_callback :before_update
          define_callback :after_update
          define_callback :before_unmount
        end
        base.extend(React::Component::ClassMethods)
      end

      def self.deprecation_warning(message)
        React::Component.deprecation_warning(name, message)
      end

      def deprecation_warning(message)
        React::Component.deprecation_warning(self.class.name, message)
      end

      def initialize(native_element)
        @native = native_element
        init_store
      end

      def emit(event_name, *args)
        params["_on#{event_name.to_s.event_camelize}"].call(*args)
      end

      def component_will_mount
        React::IsomorphicHelpers.load_context(true) if React::IsomorphicHelpers.on_opal_client?
        # set_state! initial_state if initial_state
        # State.initialize_states(self, initial_state)
        React::State.set_state_context_to(self) { run_callback(:before_mount) }
      rescue Exception => e
        self.class.process_exception(e, self)
      end

      def component_did_mount
        React::State.set_state_context_to(self) do
          run_callback(:after_mount)
          React::State.update_states_to_observe
        end
      rescue Exception => e
        self.class.process_exception(e, self)
      end

      def component_will_receive_props(next_props)
        # need to rethink how this works in opal-react, or if its actually that useful within the react.rb environment
        # for now we are just using it to clear processed_params
        React::State.set_state_context_to(self) { self.run_callback(:before_receive_props, Hash.new(next_props)) }
      rescue Exception => e
        self.class.process_exception(e, self)
      end

      def component_will_update(next_props, next_state)
        React::State.set_state_context_to(self) { self.run_callback(:before_update, Hash.new(next_props), Hash.new(next_state)) }
      rescue Exception => e
        self.class.process_exception(e, self)
      end

      def component_did_update(prev_props, prev_state)
        React::State.set_state_context_to(self) do
          self.run_callback(:after_update, Hash.new(prev_props), Hash.new(prev_state))
          React::State.update_states_to_observe
        end
      rescue Exception => e
        self.class.process_exception(e, self)
      end

      def component_will_unmount
        React::State.set_state_context_to(self) do
          self.run_callback(:before_unmount)
          React::State.remove
        end
      rescue Exception => e
        self.class.process_exception(e, self)
      end

      attr_reader :waiting_on_resources

      def update_react_js_state(object, name, value)
        if object
          name = "#{object.class}.#{name}" unless object == self
          set_state(
            '***_state_updated_at-***' => Time.now.to_f,
            name => value
          )
        else
          set_state name => value
        end
      end

      def render
        raise 'no render defined'
      end unless method_defined?(:render)

      def _render_wrapper
        React::State.set_state_context_to(self, true) do
          element = React::RenderingContext.render(nil) { render || '' }
          @waiting_on_resources =
            element.waiting_on_resources if element.respond_to? :waiting_on_resources
          element
        end
      # rubocop:disable Lint/RescueException # we want to catch all exceptions regardless
      rescue Exception => e
        # rubocop:enable Lint/RescueException
        self.class.process_exception(e, self)
      end

      def watch(value, &on_change)
        Observable.new(value, on_change)
      end

      def define_state(*args, &block)
        React::State.initialize_states(self, self.class.define_state(*args, &block))
      end
    end
  end
end

module React
  module Component
    def self.included(base)
      # note this is turned off during old style testing:  See the spec_helper
      deprecation_warning base, "The module name React::Component has been deprecated.  Use Hyperloop::Component::Mixin instead."
      base.include Hyperloop::Component::Mixin
    end
    def self.deprecation_warning(name, message)
      @deprecation_messages ||= []
      message = "Warning: Deprecated feature used in #{name}. #{message}"
      unless @deprecation_messages.include? message
        @deprecation_messages << message
        React::IsomorphicHelpers.log message, :warning
      end
    end
  end
  module ComponentNoNotice
    def self.included(base)
      base.include Hyperloop::Component::Mixin
    end
  end
end

module React
end