Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

anonymouse703's avatar

All Inertia requests must receive a valid Inertia response, however a plain JSON response was received.

I thought everything is ok until the QA test.

in the first load pagination looks fine but when I click next or the page number there's a prompt

All Inertia requests must receive a valid Inertia response, however a plain JSON response was received.

This is the controller

   public function showMineralTransactions(Request $request, $id)
    {

        $mineralTransactions = MineralTransaction::where('player_id', $id)->latest()->paginate(10);
        return response()->json([
            'mineralTransactions' => $mineralTransactions,
            'mineralTypes' => MineralTypes::array()
        ]);

    }

this is the component

<script setup>
import { ref, onMounted, computed } from "vue";
import moment from "moment";
import axios from "axios";
import Pagination from "@/Components/Pagination";

const props = defineProps({
    playerId: {
        type: Number,
        required: true,
    },
});

const mineralTransactions = ref([]);

const mineralTypes = ref([]);

const selectedMineralType = ref("All");

const pagination = ref(null);
console.log("Pagination Data", pagination);

async function fetchData() {
    try {
        const response = await axios.get(
            route("admin.players.showMineralTransactions", { id: props.playerId })
        );

        mineralTransactions.value = response.data.mineralTransactions;
        mineralTypes.value = response.data.mineralTypes;
        pagination.value = response.data.mineralTransactions;
    } catch (error) {
        console.error("Error fetching mineral log data:", error);
    }
}

onMounted(() => {
    fetchData();
});

const mineralTransactionsFiltered = computed(() => {
    // If the selected action type is "All", return all transactions
    if (selectedMineralType.value === "All") {
        return mineralTransactions.value.data;
    } else {
        // Filter the logs based on the selected action type
        return mineralTransactions.value.data.filter((mineral) => {
            return mineral.type === selectedMineralType.value;
        });
    }
});

const formattedDate = (date) => {
    return moment(date).format("MMMM DD, YYYY");
};
const formattedTime = (date) => {
    return moment(date).format("h:mm:ss A");
};
</script>
<template>
    <div class="relative inline-flex">
        <select
            class="appearance-none py-2 px-4 pr-8 rounded leading-tight focus:outline-none focus:shadow-outline bg-gray-800 text-yellow-100"
            v-model="selectedMineralType">
            <option value="All">All</option>
            <option v-for="(type, key) in mineralTypes" :value="key" :key="key">
                {{ key }}
            </option>
        </select>
    </div>
    <div class="w-8/12 table-fixed overflow-y-auto">
        <table class="mt-3">
            <thead>
                <tr
                    class="text-xs font-semibold tracking-wide text-left text-gray-500 uppercase border-b dark:border-gray-700 bg-gray-50 dark:text-gray-400 dark:bg-gray-800">
                    <th class="px-4 py-3 whitespace-nowrap">Type</th>
                    <th class="px-4 py-3 whitespace-nowrap text-right">Amount</th>
                    <th class="px-4 py-3 whitespace-nowrap text-right">Amount Before</th>
                    <th class="px-4 py-3 whitespace-nowrap text-right">Amount After</th>
                    <th class="px-4 py-3 whitespace-nowrap">Cashin ID</th>
                    <th class="px-4 py-3 whitespace-nowrap">NFT Purchase ID</th>
                    <th class="px-4 py-3 whitespace-nowrap">Energy Transaction ID</th>
                    <th class="px-4 py-3 whitespace-nowrap">Initiator ID</th>
                    <th class="px-4 py-3 whitespace-nowrap">Date</th>
                </tr>
            </thead>
            <tbody class="bg-white divide-y dark:divide-gray-700 dark:bg-gray-800">
                <template v-if="mineralTransactionsFiltered && mineralTransactionsFiltered.length">
                    <tr v-for="mineral in mineralTransactionsFiltered" :key="mineral.id"
                        class="text-gray-900 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition">
                        <td class="px-3 py-3 text-sm whitespace-nowrap">
                            {{ mineral.type }}
                        </td>
                        <td class="py-3 px-4 text-sm whitespace-nowrap text-right">
                            {{ mineral.amount }}
                        </td>
                        <td class="py-3 px-4 text-sm whitespace-nowrap text-right">
                            {{ mineral.amount_before }}
                        </td>
                        <td class="px-3 py-3 text-sm whitespace-nowrap text-right">
                            {{ mineral.amount_after }}
                        </td>
                        <td class="px-3 py-3 text-sm whitespace-nowrap">
                            {{ mineral.cashin_id }}
                        </td>
                        <td class="px-3 py-3 text-sm whitespace-nowrap">
                            {{ mineral.nft_purchase_id }}
                        </td>
                        <td class="px-3 py-3 text-sm whitespace-nowrap">
                            {{ mineral.energy_transaction_id }}
                        </td>
                        <td class="px-3 py-3 text-sm whitespace-nowrap">
                            {{ mineral.initiator_id }}
                        </td>
                        <td class="px-3 py-3 text-sm whitespace-nowrap">
                            {{ formattedDate(mineral.created_at) }}
                            {{ formattedTime(mineral.created_at) }}
                        </td>
                    </tr>
                </template>

                <template v-else>
                    <tr class="text-gray-500 dark:text-gray-400">
                        <td class="px-4 py-3 text-sm text-center italic" colspan="9">
                            No mineral transactions available.
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
        <!-- <Pagination v-if="pagination" :data="pagination" class="w-full" /> -->
        <Pagination :data="pagination" class="w-full" />
    </div>
</template>

In the other component everything is ok... only on the tabs components where I pass json instead of render the component

0 likes
2 replies
wojakmcwagies's avatar

In the controller, you need to either return Inertia component using Inertia::render() OR return back() OR return to route. Pretty much it needs to return to an Inertia pages. If you want to return plain JSON, you need to use axios, fetch, or similar things and not Inertia request like useForm or router.

anonymouse703's avatar

@wojakmcwagies

async function fetchData() {
    try {
        const response = await axios.get(
            route("admin.players.showMineralTransactions", { id: props.playerId })
        );

        mineralTransactions.value = response.data.mineralTransactions;
        mineralTypes.value = response.data.mineralTypes;
        pagination.value = response.data.mineralTransactions;
    } catch (error) {
        console.error("Error fetching mineral log data:", error);
    }
}

That's how I fetch data

Please or to participate in this conversation.