1

I'm working in a rails app for the first time and I'm trying to convert the front end to React. I'm doing this view-by view, and right now I'm working on the menu bar, which has links that work based on whether or not the user is logged in. See the original rails erb code below:

<ul class="nav-right-links">
  <% if user_signed_in? %>
    <li><%= link_to 'Account', edit_user_registration_path %></li>
    <li><%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %></li>
  <% else %>
    <li><%= link_to 'Sign in', new_user_session_path %></li>
    <li><%= link_to 'Sign up', new_user_registration_path %></li>
  <% end %>
  <li><a href="/connections/help">Help</a></li>
</ul>

I figured out that this auth is being done by a rails Gem called Devise. I want to keep the auth being done through devise, but I just need to figure out how to get some of the logic into React. If you're curious, here's some of my react code so far. Right now I'm just using hrefs, but obviously it's not responding to whether or not the user is logged in:

  render () {
    return (
      <div style={styles.container}>
        <ul style={styles.leftNav}>
          {leftLinks.map(link => {
            return (
              <li style={styles.listElement}><a style={styles.link} href={link.path}> {link.name} </a> </li>
            );
          })}
        </ul>
      </div>
    );
  }

Any help is greatly appreciated!

1 Answer 1

3

What we want is a component (lets call it LoginMenu) that replaces this ERB partial.

Lets break it down by figuring out how we are going to get rid of the specific ERB code, of which there are the following constructs:

  1. <% if user_signed_in? %> ... <% else %> ... <% end %>
  2. <%= link_to 'Account', edit_user_registration_path %>
  3. <%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %>
  4. <%= link_to 'Sign in', new_user_session_path %>
  5. <%= link_to 'Sign up', new_user_registration_path %>

What 1, 2, & 3 all need is a user_id (which might be nil) . If there is a non-nil user_id then the "user is signed in" and the id of the user can be used to construct the the edit and destroy paths. The other two paths (4, 5) are constant values.

So what your component needs is the user_id to be sent in as a prop. Then you can say something like this

if (props["user_id"]) {
  ... build and render the edit and destroy links using the value of props["user_id"]
} else {
  ... build the signin, and signup links
}

You can make little helper functions like this:

edit_user_link: function {
  <a style=... href={"/user/"+props["user_id"]+/edit"} >
}

etc...

Assuming you are using react-rails then you will have

<%= react_component "LoginMenu", user_id: @user ? @user.id : nil %>

At this point this much of the page is not "reactive" but in our experience login is one of the harder things to make reactive, so just leave as is for now.

FYI... if you are just starting out you may want to consider http://reactrb.org which will let you code the client side code in ruby, so you are not trying to learn mesh three different lanuages at once (ruby, js, JSX).

You ruby component would look like this for example (this will actually run in Stack Overflow...)

<script type="text/ruby">
# the above script tag just allows us to run in SO
# In your app User would be your user model, we are just going to stub it here

class User # < ActiveRecord::Base - just stub user for now
  def id
   12
  end
end

# Here is your component.  Normally this would be in the file 
# app/views/components/login.rb by convention

class LoginMenu < React::Component::Base
  param :user, type: User
  def render 
    ul.nav_right_links do
      if params.user #react.rb refers to props as params
        li { a(href: "/user/#{params.user.id}/edit") { "Account" } }
        li { a(href: "/user/#{params.user.id}/delete") { "Delete" } }
      else
        li { a(href: "/user/new") { "Sign Up" } }
        li { a(href: "/user/login") { "Sign In" } }
      end
      li { a(href: "/connections/help") { "Help" } }
    end
  end
end

# the following just fires up our component in stack overflow...
# in your app you would do this in the controller:
# <%= react_component "LoginMenu", user: @user %>

Element['#container'].render { LoginMenu(user: User.new) }

</script>
<div id="container"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<script src="https://rawgit.com/reactive-ruby/inline-reactive-ruby/master/inline-reactive-ruby.js"></script>

Besides http://reactrb.org which has a good basic tutorial, you can check these slides out which cover rails integration specifics: http://slides.com/mitchvanduyn/deck-1

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks - this is a pretty interesting solution. Unfortunately our team doesn't want to use reactrb, but your post got me started in the right direction, so thanks!
Glad to help! Under the hood reactrb just generates react.js calls, so you should be able to translate the ruby solution to JSX. Of course you won't be able to access your rails models directly ;-( . It would be great if you could drop in at gitter.im/zetachang/react.rb and spend a couple of minutes sharing your teams pros and cons of react.js vs react.rb!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.