Javascript 使用ReactJS在AJAX调用后处理Rails flash消息
有几篇文章描述了在AJAX调用后显示flash消息(例如,和) 我正在使用并希望这样做,并且希望利用React的动态显示渲染Javascript 使用ReactJS在AJAX调用后处理Rails flash消息,javascript,ruby-on-rails,ajax,reactjs,Javascript,Ruby On Rails,Ajax,Reactjs,有几篇文章描述了在AJAX调用后显示flash消息(例如,和) 我正在使用并希望这样做,并且希望利用React的动态显示渲染 因此,我在回答我自己的问题,即当使用下面的ReactJS回答其他可能遇到此问题的人并获得改进建议时,如何在AJAX调用后呈现flash消息。此实现主要基于关于此主题的其他So帖子(请参阅相关参考文献)。代码假定Rails4.x带有资产管道,HAML用于视图,引导用于样式设置,以及gem的使用 (更新:稍长的讨论可在上找到) 布局 以下是app/views/layouts/
因此,我在回答我自己的问题,即当使用下面的ReactJS回答其他可能遇到此问题的人并获得改进建议时,如何在AJAX调用后呈现flash消息。此实现主要基于关于此主题的其他So帖子(请参阅相关参考文献)。代码假定Rails4.x带有资产管道,HAML用于视图,引导用于样式设置,以及gem的使用 (更新:稍长的讨论可在上找到) 布局
以下是
app/views/layouts/application.html.haml
文件:
!!!
%html
%head
%title
Demo
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
= javascript_include_tag 'application', 'data-turbolinks-track' => true
= csrf_meta_tags
%body
%div.container
%div#flash_messages
= yield
请注意,div
的id为#flash_messages
。此容器div的位置决定了flash消息的显示位置
控制器下面的私有例程只是将数组的本机数组转换为头中可解析的JSON
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
after_filter :flash_to_http_header
private
def flash_to_http_header
return unless request.xhr?
return if flash.empty?
response.headers['X-FlashMessages'] = flash.to_hash.to_json
flash.discard # don't want the flash to appear when you reload page
end
end
FlashMessages
React类做了一些事情。首先,它将道具移动到状态。通常这是一种反模式,但这样做会使非反应代码在需要时触发更改。messages
函数就是触发器,它意味着由外部JS代码调用。render
的主处理假定Rails flash原生array-of-2-element-array数据结构将处理量保持在最低限度,并允许从视图直接使用组件,而不仅仅是AJAX调用。最后,local\u flash\u class
方法支持引导样式(当然可以根据需要调整其他样式)
handleFlashMessagesHeader是一个全局函数,用于将JSON转换回Rails控制器过滤器方法完成的数组。注意,它从Rails应用程序视图/布局中获取带有id标记的DOM元素
最后一部分是在页面加载时运行的,因此取决于jqueryready。React.render
(正式的React.renderComponent
)保存到一个全局变量中,以允许直接调用FlashMessages
对象的message
方法(使用的dummy
数组在第一次调用时只是为一个空的flash数组种子——这可能也可以在React类中通过空测试来处理)。每当触发ajaxComplete
时,就会调用handleFlashMessageHeader
函数并传递React对象进行更新
非AJAX因为React类假定数组的本机数组,所以视图可以简单地调用
= react-component 'FlashMessages', flash, :div
而是显示它,但由于不支持动态响应,因此它的用处当然较小。但是,无论哪种方式调用它的能力都为某些用例提供了更大的灵活性。我无法获得@rdnewman对Rails 5和react Rails 1.9.0(对应于react 15.3.0)的回答.我认为React中发生了一些变化,不允许外部访问函数,因此在
handleFlashMessagesHeader()
中调用.messages()
无法工作(未找到函数)
我将答案改编为适合我的答案。我只是在学习如何反应,所以可能有更好的方法,但我得到的是:
app/controllers/application\u controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
after_action :flash_to_http_header, if: -> { request.xhr? }
private
def flash_to_http_header
return if flash.empty?
response.headers['X-FlashMessages'] = flash.to_hash.to_json
flash.discard
end
end
app/views/layouts/application.html.erb
<%= react_component 'FlashMessages', { data: flash.to_hash } %>
这将在页面加载时呈现标准flash消息,并在任何Ajax请求后更新/替换它们。如果您使用react rails
gem,您只需将文件放入components
目录,一切都应该正常
@FlashMessages = React.createClass
getInitialState: ->
messages: @props.data
getDefaultProps: ->
messages: {}
componentDidMount: ->
$(document).ajaxComplete ((event, xhr, settings) ->
header_messages = xhr.getResponseHeader('X-FlashMessages')
messages = {}
if header_messages
messages = JSON.parse(header_messages)
@replaceState {messages: messages}
).bind(this)
messageClass: (messageType) ->
if messageType == 'notice'
return 'alert alert-warning'
if messageType == 'success'
return 'alert alert-success'
return 'alert alert-error'
render: ->
React.DOM.div
className: 'flash-messages'
for messageType of @state.messages
React.DOM.div
className: @messageClass(messageType)
key: messageType
@state.messages[messageType]
<%= react_component 'FlashMessages', { data: flash.to_hash } %>