Reputation: 247
I'm trying to access an api backend in a React/Rails app. I'm referencing this tutorial (it's a little outdated, but works with a few tweaks). I can't seem to connect to the backend. How can I resolve / troubleshoot these errors?
Fetch console error:
Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
Rails server log error:
Started GET "/api/v1/playlists/index" for ::1 at 2024-09-05 08:59:11 -0400
Processing by Api::V1::PlaylistsController#index as */*
Playlist Load (0.4ms) SELECT "playlists".* FROM "playlists"
↳ app/controllers/api/v1/playlists_controller.rb:5:in `index'
ActiveStorage::Attachment Load (0.2ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ? [["record_id", 1], ["record_type", "Playlist"], ["name", "image"], ["LIMIT", 1]]
↳ app/controllers/api/v1/playlists_controller.rb:5:in `index'
ActiveStorage::Blob Load (0.1ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/controllers/api/v1/playlists_controller.rb:5:in `index'
Completed 500 Internal Server Error in 51ms (ActiveRecord: 0.7ms | Allocations: 7845)
fatal (exception reentered):
javascript/components/Playlists.jsx (truncated for clarity)
import { Table, message, Popconfirm } from "antd";
import React from "react";
class Playlists extends React.Component {
...
loadPlaylists = () => {
const url = "api/v1/playlists/index";
fetch(url)
.then((data) => {
if (data.ok) {
return data.json();
}
console.log(data.json())
throw new Error("Network error.");
})
...
};
...
render() {
return (
<>
<Table className="table-striped-rows" dataSource={this.state.playlists} columns={this.columns} pagination={{ pageSize: 5 }} />
</>
);
}
}
export default Playlists;
controllers/api/v1/playlists_controller.rb:
class Api::V1::PlaylistsController < ApplicationController
# GET /playlists or /playlists.json
def index
@playlists = Playlist.all
render json: @playlists
end
end
routes.rb
Rails.application.routes.draw do
root 'page#index'
namespace :api do
namespace :v1 do
get 'playlists/index'
post 'playlists/create'
delete 'playlists/:id', to: 'playlists#destroy'
end
end
end
Let me know if I'm missing anything here. Thank you!
***UPDATE: I'm finding that all other models work, when I replace "Playlist.all" in the controller. For example, using the Track model, which has a youtube video ID, and a reference to the playlist(s) it belong to:
controllers/api/v1/playlists_controller.rb:
class Api::V1::PlaylistsController < ApplicationController
# GET /playlists or /playlists.json
def index
@playlists = Track.all
render json: @playlists
end
end
Works perfectly fine. Obviously the table above isn't filled out because the fields are different, but the app is able to access Tracks without returning a 500 error..
Upvotes: 0
Views: 106
Reputation: 13061
The problem is here and caused by assuming an unsuccessful response contains JSON. Your example clearly contains an HTML error page.
fetch(url)
.then((data) => {
if (data.ok) {
return data.json();
}
console.log(data.json())
throw new Error("Network error.");
})
You would be better off logging data.text()
:
fetch(url)
.then((data) => {
if (data.ok) {
return data.json();
}
console.log(data.text()) // UPDATE THIS
throw new Error("Network error.");
})
Also, I wouldn't assume that a failed request is only caused by a network error either.
Upvotes: 0