【问题标题】:Hyperstack and MaterialUI Drawer Toggling State is causing the drawer to open and close repeatedlyHyperstack 和 MaterialUI 抽屉切换状态导致抽屉反复打开和关闭
【发布时间】:2019-03-25 17:15:48
【问题描述】:

我正在 Hyperstack 项目中使用 MaterialUI 实现标题栏和菜单抽屉。我有两个组件,一个Header 组件和一个Menu 组件。 Menu 组件是可扩展的Drawer。我将状态存储在Header 组件中,并将它和一个处理程序传递给Menu 组件,以在单击抽屉关闭按钮时切换抽屉状态。出于某种原因,抽屉只是快速而反复地打开和关闭。

在我实现关闭按钮之前,抽屉可以正常打开。我尝试将状态向上移动到主应用程序组件并将其一直向下传递,但它会产生相同的结果。我尝试在Header 组件上设置一个类函数,并从Menu 组件中调用它,而不是传入事件处理程序。

Header 组件

class Header < HyperComponent
  before_mount do
    @drawer_open = false
  end

  def toggle_drawer
    mutate @drawer_open = !@drawer_open
  end

  render(DIV) do
    AppBar(position: 'static', class: 'appBar') do
      Toolbar do
        IconButton(class: 'menuButton', color: 'inherit', aria_label: 'Menu') do
          MenuIcon(class: 'icon')
        end
        .on(:click) do
          toggle_drawer
        end
        Typography(variant: 'h6', color: 'inherit', class: 'grow') { 'Admin Main' }
        Button(color: 'inherit', class: 'float-right') { 'Login' } # unless App.history != '/admin'
      end
    end
    Menu(open_drawer: @drawer_open, toggle_drawer: toggle_drawer)
  end
end

Menu 组件

class Menu < HyperComponent
  param :open_drawer
  param :toggle_drawer

  def menu_items
    %w(Main Inventory Customers)
  end

  def is_open?
    @OpenDrawer
  end

  render(DIV) do
    Drawer(className: 'drawer, drawerPaper', variant: 'persistent', anchor: 'left', open: is_open?) do
      IconButton(className: 'drawerHeader') { ChevronLeftIcon() }
      .on(:click) { @ToggleDrawer }

      List do
        menu_items.each do |mi|
          ListItem(button: true, key: mi) { ListItemText(primary: mi) }
        end
      end
    end
  end
end

我希望抽屉在单击打开按钮时打开并在单击关闭按钮时关闭,但它只是非常迅速地打开和关闭。

【问题讨论】:

    标签: ruby reactjs ruby-on-rails-3 opalrb hyperstack


    【解决方案1】:

    它快速打开和关闭的原因是您将toggle_drawerHeader 组件传递到Menu 组件。每次调用 toggle_drawer 时,它都会更改状态变量 @drawer_open,并重新渲染组件,然后进行泡沫冲洗重复。

    您需要做的是将proc 传递给Menu,然后让Menu 调用on_click 处理程序中的proc。

    所以它看起来像这样:

    class Header < HyperComponent
     ...
     render(DIV) do
       ...
       Menu(open_drawer: @drawer_open, toggle_drawer: method(:toggle_drawer))
     end
    end
    

    class Menu < HyperComponent
      ...
      param :toggle_drawer
      ...
          IconButton(className: 'drawerHeader') { ChevronLeftIcon() }
          .on(:click) { @ToggleDrawer.call } # note you have to say .call
      ...
    end
    

    顺便说一句,关于method(:toggle_drawer) 工作原理的好文章here 并比较它在 Javascript 中的相同行为。

    但是等等! Hyperstack 有一些很好的语法糖来提高可读性。

    您应该使用fires 方法声明它,而不是将toggle_drawer 声明为普通参数,这表明您将向调用组件触发一个事件(或回调)。这不仅会让你的生活更轻松,而且还会向读者宣布你的意图。

    class Menu < HyperComponent
      ...
      fires :toggle_drawer # toggle_drawer is a callback/event that we will fire!
      ...
          IconButton(className: 'drawerHeader') { ChevronLeftIcon() }
          .on(:click) { toggle_drawer! } # fire the toggle_drawer event (note the !) 
      ...
    end
    

    现在Header 可以使用正常的事件处理程序语法:

    class Header < HyperComponent
     ...
     render(DIV) do
       ...
       Menu(open_drawer: @drawer_open)
       .on(:toggle_drawer) { toggle_drawer }
     end
    end 
    

    顺便说一句,如果我能给出一点风格建议:由于菜单只能关闭我称之为事件的抽屉,并且在事件处理程序中我只会直接改变抽屉状态(并且只是失去 toggle_drawer 方法)。

    这样读代码就很清楚你要转换到什么状态了。

    生成的代码如下所示:

    class Header < HyperComponent
      before_mount do
        @drawer_open = false  # fyi you don't need this, but its also not bad practice
      end
    
      render(DIV) do
        AppBar(position: 'static', class: 'appBar') do
          Toolbar do
            IconButton(class: 'menuButton', color: 'inherit', aria_label: 'Menu') do
              MenuIcon(class: 'icon')
            end.on(:click) { mutate @drawer_open = true }
            Typography(variant: 'h6', color: 'inherit', class: 'grow') { 'Admin Main' }
            Button(color: 'inherit', class: 'float-right') { 'Login' } # unless App.history != '/admin'
          end
        end
        Menu(open_drawer: @drawer_open)
        .on(:close_drawer) { mutate @drawer_open = false }
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多