React / Redux - 父项和子项之间的菜单和项目事件

时间:2016-03-02 17:40:35

标签: reactjs coffeescript redux cjsx

我正在尝试从头开始使用MenuItem构建一个菜单。我正在使用React 0.14和Redux,以及CoffeeScript(cjsx)。 (我刚刚开始使用所有这些)

我被卡住了,因为我不知道如何给MenuItem提供对回调函数match = re.search(r"On ([0-9,-, ]+)Bob used ([0-9\.]+)", line.strip()) if match is not None: ... do stuff with match.group() here ... ... but not here ... 的引用。因为它们是通过onChildrenClick生成的,所以我不知道我应该在那里添加{this.props.children}

Menu.cjsx

props

MenuItem.cjsx

React = require 'react'

class Menu extends React.Component

    @propTypes =
        children: React.PropTypes.array.isRequired

    render: ->
        <div className="ui pointing menu">
            {this.props.children} # I don't see how I can bind the "onChildrenClick" function to the child, because they're generated outside of this scope. Maybe by looping on "this.props.children"? I tried but it wasn't successful. 
        </div>

    onChildrenClick: (event) ->
        console.log event

module.exports = Menu

以下是我如何构建菜单及其项目:

React = require 'react'
classNames = require('classnames')

class MenuItem extends React.Component

    @propTypes =
        label: React.PropTypes.string.isRequired
        active: React.PropTypes.bool

    constructor: (props) ->
        super props

        @state =
            classes: classNames(
                'ui'
                'item'
                'active': this.props.active
            )

    render: ->
        <a className={@state.classes} onClick={@onClick}>
            { this.props.label }
        </a>

    onClick: =>
        console.log Object.assign @state.classes, {active: !@state.classes.active}
        @setState({classes: Object.assign @state.classes, {active: true}})
        console.log @state.classes # I need to notify the parent so it can notify the current active children to get disabled.

module.exports = MenuItem

在示例中,我手动生成“菜单1 ... 3”,但它们实际上是动态生成的。

我不知道我是否在这里采取了正确的方法。也许我应该使用Redux呢?最后,我应该使用<Menu> <MenuItem active={true} label="Menu 1"></MenuItem> <MenuItem label="Menu 2"></MenuItem> <MenuItem label="Menu 3"></MenuItem> </Menu> ,因为每个MenuItem应该有自己的url(类似Angular,例如Routes

我也想知道给一个 MenuItem 内容的最佳方法是什么。感谢您的见解。

2 个答案:

答案 0 :(得分:1)

这可能是React.Children的候选人,您可以将props指定为传递给任何abritrary子元素 - 在这种情况下onClick

<强> Menu.jsx

<div className="ui pointing menu">
{
      React.Children.map(this.props.children,
          function(child) {
              return React.cloneElement(child, {
                  onClick: this.onClick
              });
          }.bind(this)
      )
 }
</div>

但我可能会建议一种替代方法,您可以将列表项传递给Menu组件本身,然后可以单独呈现每个列表项,而不仅仅是this.props.children

Menu.jsx(Alt)

render() {
    return (
        <div className="ui pointing menu">
          {
             this.props.menuItems.map((item, index) => (
                 <MenuItem item={item} onClick={(e) => this.onClick(e, item)} }/>
             )
          }
        </div>
    )
}

答案 1 :(得分:0)

我建议将onClick函数作为MenuItem的道具从您呈现Menu的任何地方传递。

E.g。

menu_wrapper.js

// This is a functional component because it is 'dumb' - does not have state

React = require('react')
Menu = require('menu')
MenuItem = require('menu_item')

menuWrapper = (props)=>
  onMenuItemClick = (e)=>
    console.log(e)

  menuItems = ()=>
    props.list.map(function(item) {
      isActive = (item.label == props.activeItem)
      <MenuItem onClick={onMenuItemClick} active={isActive} label={item.label}/>
    }

  <div id="menu-wrapper">
    <Menu>
      {menuItems()}
    </Menu>
  </div>

menu.js

// Also a 'dumb' component - component without state

React = require('react')

Menu = (props)=>
  <div className="ui pointing menu">
    {props.children}
  </div>

module.exports = Menu

menu_item.js

React = require 'react'
classNames = require('classnames')

class MenuItem extends React.Component
  @propTypes =
      label: React.PropTypes.string.isRequired
      active: React.PropTypes.bool
      onClick: React.PropTypes.func.isRequired

  constructor: (props) ->
      super props

      @state =
          classes: classNames(
              'ui'
              'item'
              'active': this.props.active
          )

  render: ->
      <a className={@state.classes} onClick={@onClick}>
          { this.props.label }
      </a>

  onClick: (e)=>
      @props.onClick(e)
      console.log Object.assign @state.classes, {active: !@state.classes.active}
      @setState({classes: Object.assign @state.classes, {active: true}})
      console.log @state.classes # I need to notify the parent so it can notify the current active children to get disabled.

module.exports = MenuItem

最后,考虑从CoffeeScript迁移到ES6。您在CoffeeScript中获得的大部分内容现在都可以在ES6中使用,还有一些。也就是说,我确实错过了隐含的回报。