Skip to content

Commit 6194793

Browse files
committed
demo react-over-hotwired and proof #1508 fixed
1 parent acfe281 commit 6194793

File tree

16 files changed

+312
-2
lines changed

16 files changed

+312
-2
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
55

66
ruby "3.1.2"
77

8-
gem "react_on_rails", "14.0.0"
8+
gem "react_on_rails", path: '../react_on_rails'
99
gem "shakapacker", "7.2.1"
1010

1111
# Bundle edge Rails instead: gem "rails", github: "rails/rails"

app/controllers/comments_controller.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def create
3333
format.html { redirect_to @comment, notice: I18n.t("Comment was successfully created.") }
3434
end
3535
format.json { render :show, status: :created, location: @comment }
36+
format.turbo_stream
3637
else
3738
if turbo_frame_request?
3839
format.html
@@ -99,6 +100,10 @@ def inline_form
99100
end
100101
end
101102

103+
def test_1508
104+
@comment = Comment.new
105+
end
106+
102107
private
103108

104109
def set_comments

app/controllers/pages_controller.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ def simple; end
3838

3939
def rescript; end
4040

41+
def hotwired
42+
@props = comments_json_string
43+
end
44+
4145
private
4246

4347
def set_comments
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<%= form_for(@comment, html: { class: "flex flex-col gap-4" }) do |f| %>
2+
<% if @comment.errors.any? %>
3+
<div id="error_explanation" class="prose bg-pink-100 p-4 mb-4 border border-pink-200 rounded text-red-800 prose-strong:text-red-800 prose-ul:my-1">
4+
<h2><%= pluralize(comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
5+
6+
<ul>
7+
<% comment.errors.full_messages.each do |message| %>
8+
<li><%= message %></li>
9+
<% end %>
10+
</ul>
11+
</div>
12+
<% end %>
13+
14+
<div class="field">
15+
<%= f.label :author, 'Your Name' %><br>
16+
<%= f.text_field :author, class: "px-3 py-1 leading-4 border border-gray-300 rounded" %>
17+
</div>
18+
<div class="field">
19+
<%= f.label :text, 'Say something using markdown...' %><br>
20+
<%= f.text_area :text, class: "px-3 py-1 leading-4 border border-gray-300 rounded" %>
21+
</div>
22+
<div class="actions">
23+
<%= f.submit 'Post', class: "self-start px-3 py-1 font-semibold border-0 rounded text-sky-50 bg-sky-600 hover:bg-sky-800 cursor-pointer" %>
24+
</div>
25+
26+
<h1>Below is a react component which render inside a form (that will proof #1508 is fixed), You can turn-off the flag `force_load` and this below form will not show. </h1>
27+
<div class="mx-10 border border-red-600 rounded">
28+
<%= react_component('HotwiredCommentForm', props: { }, prerender: false, force_load: true) %>
29+
</div>
30+
<% end %>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<%= turbo_stream.prepend "comments" do %>
2+
<div>
3+
<h2 class="text-blue-800"><%= @comment.author %></h2>
4+
<span><%= markdown_to_html(@comment.text) %></span>
5+
</div>
6+
<% end %>
7+
8+
<%= turbo_stream.update "comment-form" do %>
9+
<%= link_to "New Comment", new_comment_path, data: {turbo_stream: true} %>
10+
<% end %>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<%= turbo_stream.update "comment-form" do %>
2+
<div class="p-5 m-5 border border-red-600 rounded">
3+
<h2>New Comment</h2>
4+
5+
<%= react_component('HotwiredCommentForm', props: { }, prerender: false, force_load: true) %>
6+
</div>
7+
<% end %>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<%= turbo_stream.replace dom_id(@comment), target: '_top' do %>
2+
<%= render partial: 'form_1508' %>
3+
<% end %>

app/views/pages/hotwired.html.erb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<h2>Demo React Over Hotwired</h2>
2+
3+
<%= react_component('HotwiredCommentScreen', props: @props, prerender: false) %>
4+
5+
6+
<%= turbo_frame_tag "new_comment" do %>
7+
<%= link_to "proof that #1508 fixed", "/test_1508", data: {turbo_stream: true} %>
8+
<% end %>

client/app/bundles/comments/components/CommentBox/CommentList/CommentList.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export default class CommentList extends BaseComponent {
7878
<div>
7979
{this.errorWarning()}
8080

81-
<TransitionGroup className="commentList" component="div">
81+
<TransitionGroup id="comments" className="commentList" component="div">
8282
{commentNodes}
8383
</TransitionGroup>
8484
</div>
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// eslint-disable-next-line max-classes-per-file
2+
import React from 'react';
3+
import request from 'axios';
4+
import Immutable from 'immutable';
5+
import _ from 'lodash';
6+
import ReactOnRails from 'react-on-rails';
7+
import { IntlProvider, injectIntl } from 'react-intl';
8+
import BaseComponent from 'libs/components/BaseComponent';
9+
import SelectLanguage from 'libs/i18n/selectLanguage';
10+
import { defaultMessages, defaultLocale } from 'libs/i18n/default';
11+
import { translations } from 'libs/i18n/translations';
12+
13+
import { Turbo } from '@hotwired/turbo-rails';
14+
import CommentForm from '../CommentBox/CommentForm/CommentForm';
15+
import css from './HotwiredCommentScreen.module.scss';
16+
17+
class HotwiredCommentForm extends BaseComponent {
18+
constructor(props) {
19+
super(props);
20+
21+
this.state = {
22+
isSaving: false,
23+
submitCommentError: null,
24+
};
25+
26+
_.bindAll(this, 'handleCommentSubmit');
27+
}
28+
29+
componentDidMount() {
30+
}
31+
32+
handleCommentSubmit(comment) {
33+
this.setState({ isSaving: true });
34+
35+
const requestConfig = {
36+
responseType: 'text/vnd.turbo-stream.html',
37+
headers: ReactOnRails.authenticityHeaders(),
38+
};
39+
40+
return request
41+
.post('comments.turbo_stream', { comment }, requestConfig)
42+
.then(r => r.data)
43+
.then(html => {
44+
Turbo.renderStreamMessage(html)
45+
})
46+
.then(() => {
47+
const { $$comments } = this.state;
48+
const $$comment = Immutable.fromJS(comment);
49+
50+
this.setState({
51+
$$comments: $$comments.unshift($$comment),
52+
submitCommentError: null,
53+
isSaving: false,
54+
});
55+
})
56+
.catch((error) => {
57+
this.setState({
58+
submitCommentError: error,
59+
isSaving: false,
60+
});
61+
});
62+
}
63+
64+
render() {
65+
const { handleSetLocale, locale, intl } = this.props;
66+
const cssTransitionGroupClassNames = {
67+
enter: css.elementEnter,
68+
enterActive: css.elementEnterActive,
69+
exit: css.elementLeave,
70+
exitActive: css.elementLeaveActive,
71+
};
72+
73+
return (
74+
<div className="commentBox prose max-w-none prose-a:text-sky-700 prose-li:my-0">
75+
{SelectLanguage(handleSetLocale, locale)}
76+
77+
<CommentForm
78+
isSaving={this.state.isSaving}
79+
actions={{ submitComment: this.handleCommentSubmit }}
80+
error={{ error: this.state.submitCommentError, nodeRef: React.createRef(null) }}
81+
cssTransitionGroupClassNames={cssTransitionGroupClassNames}
82+
/>
83+
84+
</div>
85+
);
86+
}
87+
}
88+
89+
export default class I18nWrapper extends BaseComponent {
90+
constructor(props) {
91+
super(props);
92+
93+
this.state = {
94+
locale: defaultLocale,
95+
};
96+
97+
_.bindAll(this, 'handleSetLocale');
98+
}
99+
100+
handleSetLocale(locale) {
101+
this.setState({ locale });
102+
}
103+
104+
render() {
105+
const { locale } = this.state;
106+
const messages = translations[locale];
107+
const InjectedHotwiredCommentForm = injectIntl(HotwiredCommentForm);
108+
109+
return (
110+
<IntlProvider locale={locale} key={locale} messages={messages}>
111+
<InjectedHotwiredCommentForm
112+
/* eslint-disable-next-line react/jsx-props-no-spreading */
113+
{...this.props}
114+
locale={locale}
115+
handleSetLocale={this.handleSetLocale}
116+
/>
117+
</IntlProvider>
118+
);
119+
}
120+
}

0 commit comments

Comments
 (0)