Naji
Naji

Reputation: 732

How to properly get an AJAX request to React from Rails

I'm fairly new to Rails, although I generally understand the structure/how it works. Side-note, my goal here is to have 1 javascript import tag in a views/home/application.html.erb that will import a single React file, which will then import the rest of my components in a tree-like structure. I'm used to this method because of my experience with Express so please let me know if this is not the standard way of doing things with Rails.

The current issue I'm facing however is that I can't/don't know how to get my Rails controller to send my instance variable as a response to my axios request. I'm expecting my browser to console.log('TESTING MY RAILS ROUTE'), but rather it's logging the entire HTML response.

Index.jsx (in javascript/components)

import React from "react"
import ReactDOM from 'react-dom'
import axios from 'axios'


class Index extends React.Component {

  componentDidMount() {
    axios.get('/login')
    .then(res => {
      console.log(res.data)
    })
  }

  render() {
    return (
        <div>
            <h1>Testing Axios</h1>
        </div>
    )
  }
}

export default Index

config/routes.rb

Rails.application.routes.draw do
    get 'welcome/index'

    resources :login

    root 'welcome#index'

end

controllers/login_controller.rb

class LoginController < ApplicationController

    def index
        @test = 'TESTING MY RAILS ROUTE'
    end
end

index.html.erb (in views/welcome)

<%= react_component('Index') %>

Upvotes: 1

Views: 2316

Answers (2)

grizzthedj
grizzthedj

Reputation: 7505

You need to configure your Rails controller to respond with json as it is currently responding with HTML type response.

Since you are using React with Rails, I'm assuming that you want your Rails API to always return JSON for React to render.

Using the responders gem can help simplify this implementation, and have less code in your controllers.

Add gem 'responders' to your Gemfile. Also, identify the login resource in your routes.db to be json by default, like so:

resources :login, defaults: {format: :json}

Now apply this change at the controller level to always respond with JSON. Add respond_to :json at the top of your controller. Then use respond_with in your controller actions. respond_with will render json in all actions of your controller, as long as respond_to :json is defined at the top.

class LoginController < ApplicationController
  respond_to :json

  def index
    @test = 'TESTING MY RAILS ROUTE'
    respond_with @test
  end
end

Alternatively, you can also respond with json for an individual controller action only, by using respond_to within the controller action.

Upvotes: 1

PrimeTimeTran
PrimeTimeTran

Reputation: 2137

Rails has a convention that you need to choose the format to respond to if it's not the default. By default, Rails controller actions respond to html requests.

You should be able to configure this controller action to respond to both html and Ajax requests by adding the following code.

def index
  @test = 'TESTING MY RAILS ROUTE'

  respond_to do |format|
    format.js json: @test, status: :ok
    format.html
  end 
end

Upvotes: 0

Related Questions