Javascript FB React onClick不';我从普什图州回来时不工作

Javascript FB React onClick不';我从普什图州回来时不工作,javascript,pushstate,reactjs,Javascript,Pushstate,Reactjs,我用ReactJS呈现了一些按钮,它们的onClick绑定到一个作为prop传入的函数。单击按钮时,它将调用一个函数,该函数设置一个pushState,然后呈现一个新组件。这很好,但返回到第一页后,按钮停止响应单击 // _init.js.coffee window.TD or= {} # Rendering render_fan = -> window.history.pushState({}, "Fan Demo | Tunetap", '/fan') render('fan

我用ReactJS呈现了一些按钮,它们的
onClick
绑定到一个作为
prop
传入的函数。单击按钮时,它将调用一个函数,该函数设置一个
pushState
,然后呈现一个新组件。这很好,但返回到第一页后,按钮停止响应单击

// _init.js.coffee
window.TD or= {}

# Rendering
render_fan = ->
  window.history.pushState({}, "Fan Demo | Tunetap", '/fan')
  render('fan')
render_artist = ->
  window.history.pushState({}, "Artist Demo | Tunetap", '/artist')
  render('artist')
render_venue = ->
  window.history.pushState({}, "Venue Demo | Tunetap", '/venue')
  render('venue')
render = (arg) ->
  target = document.getElementById('content')
  role_children = { render_fan: render_fan, render_artist: render_artist, render_venue: render_venue }
  if arg == 'root'
    React.renderComponent(TD.Root(role_children), target)
  else if arg == 'fan'
    React.renderComponent(TD.FanRoot(role_children), target)
  else if arg == 'artist'
    React.renderComponent(TD.ArtistRoot(role_children), target)
  else if arg == 'venue'
    React.renderComponent(TD.VenueRoot(role_children), target)
  else render_404()
render_404 = -> React.renderComponent(TD.Error404(), document.getElementById('content'))

# Routing
pathname = window.location.pathname.slice(1)
if pathname.length < 1
  render('root')
else if pathname == 'fan' || pathname == 'artist' || pathname == 'venue'
  render(pathname)
else render_404()

// root.js.coffee
window.TD or= {}
TD.Root = React.createClass
  render: ->
    React.DOM.div
      className: 'container'
      children: [
        React.DOM.div
          className: 'row page-header'
          children: [
            React.DOM.h1
              children: 'Tunetap demo'
            React.DOM.p
              children: 'Select a role to get started'
          ]
        React.DOM.div
          className: 'row'
          children: [
            React.DOM.div
              className: 'col-sm-4'
              children: 
                React.DOM.button
                  className: 'btn btn-default col-sm-10 col-sm-offset-1'
                  children: 'Fan'
                  onClick: @props.render_fan
            React.DOM.div
              className: 'col-sm-4'
              children: 
                React.DOM.button
                  className: 'btn btn-default col-sm-10 col-sm-offset-1'
                  children: 'Artist'
                  onClick: @props.render_artist
            React.DOM.div
              className: 'col-sm-4'
              children: 
                React.DOM.button
                  className: 'btn btn-default col-sm-10 col-sm-offset-1'
                  children: 'Venue'
                  onClick: @props.render_venue
          ]
      ]
TD.FanRoot = React.createClass
  render: ->
    React.DOM.p
      children: 'Fan root'
TD.ArtistRoot = React.createClass
  render: ->
    React.DOM.p
      children: 'Artist root'
TD.VenueRoot = React.createClass
  render: ->
    React.DOM.p
      children: 'Venue root'
/\u init.js.coffee
window.TD或={}
#渲染
渲染_fan=->
window.history.pushState({},“Fan Demo | Tunetap”,“/Fan”)
渲染('风扇')
渲染艺术家=->
window.history.pushState({},“艺术家演示”| Tunetap“,“/Artist”)
渲染(“艺术家”)
渲染地点=->
window.history.pushState({},“场馆演示| Tunetap”,“/venture”)
渲染(“场地”)
呈现=(arg)->
target=document.getElementById('content')
role_children={render_fan:render_fan,render_艺术家:render_艺术家,render_场地:render_场地}
如果arg=='root'
React.renderComponent(TD.Root(角色\子角色)、目标)
如果arg=='fan'
React.renderComponent(TD.FanRoot(角色\子角色),目标)
如果arg=='艺术家'
React.renderComponent(TD.ArtistRoot(角色/子角色),目标)
否则,如果arg==‘场地’
React.renderComponent(TD.VenueRoot(角色\子角色),目标)
else render_404()
render_404=->React.renderComponent(TD.Error404(),document.getElementById('content'))
#路由
pathname=window.location.pathname.slice(1)
如果pathname.length<1
呈现('根')
否则,如果路径名='fan'| |路径名=='Artister'| |路径名=='venue'
渲染(路径名)
else render_404()
//根咖啡
window.TD或={}
TD.Root=React.createClass
渲染:->
React.DOM.div
类名:“容器”
儿童:[
React.DOM.div
类名:“行页眉”
儿童:[
React.DOM.h1
儿童:“Tunetap演示”
React.DOM.p
子项:“选择要开始的角色”
]
React.DOM.div
类名:“行”
儿童:[
React.DOM.div
类名:“col-sm-4”
儿童:
React.DOM.button
类名:“btn btn默认列-sm-10列-sm-offset-1”
孩子们:“范”
onClick:@props.render\u fan
React.DOM.div
类名:“col-sm-4”
儿童:
React.DOM.button
类名:“btn btn默认列-sm-10列-sm-offset-1”
儿童:“艺术家”
onClick:@props.render\u艺术家
React.DOM.div
类名:“col-sm-4”
儿童:
React.DOM.button
类名:“btn btn默认列-sm-10列-sm-offset-1”
儿童:“地点”
onClick:@props.render\u地点
]
]
TD.FanRoot=React.createClass
渲染:->
React.DOM.p
儿童:'扇根'
TD.ArtistRoot=React.createClass
渲染:->
React.DOM.p
儿童:“艺术家根”
TD.VenueRoot=React.createClass
渲染:->
React.DOM.p
儿童:'场地根'

感谢您的现场演示。我已经确定React 0.8和Rails的TurboLink之间的交互存在问题。以下是所发生情况的摘要:

  • 在初始页面加载时,会对JavaScript文件进行评估,从而加载jQuery、jQuery ujs、TurboLink、React和您的应用程序代码。运行初始渲染代码,它将
    组件渲染为
    #内容
    。因为React依赖于事件委派来实现性能,所以它将其事件处理程序附加到文档中

  • 当您单击“Fan”按钮时,将调用
    render\u Fan
    ,它为
    /Fan
    推送一个历史记录条目,并呈现
    FanRoot
    组件,替换
    \content
    的现有子级

  • 单击“上一步”按钮时,浏览器会将URL设置回
    /
    ,并触发一个
    popstate
    事件,TurboLink会捕获该事件。Turbolinks恢复
    标记的原始内容,这是因为您的JS加载在页面的主体而不是头部

    这会导致重新运行所有的JS,导致第二个单独的React副本被初始化(并导致再次运行应用程序代码,这就是根组件重新提交的方式)。React的第二个副本会将自己的事件侦听器附加到文档中,但React 0.8有一个错误,React的第二个副本不会添加自己的事件侦听器,因此只有React的第一个副本接收单击事件,但它不知道第二个React存储的onClick处理程序,因此不会发生任何事情

  • 较新版本的React没有这个问题——它们能够封装不同的版本,因此每个React实例都会正确地保留自己的事件处理程序。我用React 0.10.0测试了你的应用程序,它运行正常


    但是,我认为您在这里使用TurboLink是不正确的,可能会在将来给您带来问题。听起来要正确使用TurboLink,您应该在页面中添加脚本元素
    ,但由于看起来您是在单独使用React构建一个页面应用程序,您可能希望完全禁用TurboLink,只需自己绑定到
    popstate
    ,以便在单击“上一步”按钮时重新渲染。

    我认为您的代码中没有任何错误。你能在我能看到问题的地方做一个简单的现场演示吗?把代码放在这里的演示中:如果你点击主页上的按钮,它会加载一个新的视图。单击返回,按钮将停止工作。Ben!禁用的TurboLink、跟踪历史记录和绑定到
    popstate
    看起来正常工作