I am learning nuxtjs3. I am trying to get data in the template with fetch. I am following a certain tutorial but unfortunately I am stuck. I am using mysql2 library in the app and a mysql local database. But I am receiving Error: GET http://localhost:3000/api/users/index 404 (Page not found: /api/users/index) in the console. What am I doing wrong.
Below is the database.ts file
import mysql from 'mysql2/promise'
const db = await mysql.createConnection({
host: 'localhost',
user: 'myuser',
password: 'mypass',
database: "mydb"
})
export default db
Below is the index.ts file
import type { IncomingMessage, ServerResponse } from 'http'
import db from '~~/server/middleware/database'
export default async (req: IncomingMessage, res:ServerResponse) => {
const [rows,fields] = await db.execute("SELECT * FROM clients")
return{
staus: res.statusCode,
columns: fields.map((i: any) => i.name),
entries: rows,
message: res.statusMessage
}
}
Below is the index.vue file where I want to display the data.
<script setup>
import { ref, onMounted } from 'vue'
const entries = ref([])
const setEntries = async () => {
const response = await fetch('/api/users/index')
const data = await response.json()
if('entries' in data) {
entries.value = data.entries
}
}
onMounted(setEntries)
</script>
<template>
<table class="table table-bordered table-striped mt-3">
<thead>
<tr>
<th>Client Phone</th>
<th>Client Email</th>
<th style="width: 130px;">Action</th>
</tr>
</thead>
<tbody>
<tr v-for="user in entries" :key="user.client_phone">
<td>{{ user.client_phone }}</td>
<td>{{ user.client_email }}</td>
</tr>
</tbody>
</table>
</div>
</template>
Below is the arrangement of the files and folders of the app.
What am doing wrong to get Error: GET 404 (Page not found: /api/users/index)
Since nobody else has responded and despite not having tried the nuxt fetch API my self, my best guess from reading the Nitro Server Engine docs is that you should be using $fetch not fetch.
fetch is native javascript fetch API thus wont have any attribution to the application and the API endpoint your calling.
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
$fetch is a nuxt wrapper for fetch and I assume will be injecting a baseURL and various headers to make it work.
https://nuxt.com/docs/api/utils/dollarfetch#fetch
const response = await $fetch('/api/users/index')
The next problem I can see is according to the server directory docs, the export in server/api/users/index.ts should use defineEventHandler:
import db from '~~/server/middleware/database'
export default defineEventHandler(async (event) => {
const [rows,fields] = await db.execute("SELECT * FROM clients")
return {
staus: res.statusCode,
columns: fields.map((i: any) => i.name),
entries: rows,
message: res.statusMessage
}
})
Related
target: 'static'
ssr: false
I have configured my project with ssg.
If you look at fetch in the official nuxt documentation, it says that fetch is executed when a page is created and cached in the client.
However, when data is fetched from fetch and the corresponding url is accessed, an empty area appears and then the content is filled. This means calling from the client.
How can fetch be executed when page is created and all db data can be seen when url is accessed?
<template>
<div>
{{ testData }}
</div>
</template>
<script>
import { defineComponent, ref, useContext, useFetch } from '#nuxtjs/composition-api'
export default defineComponent({
name: 'Test',
fetchOnServer: false,
setup () {
const testData = ref({})
const { $axios } = useContext()
useFetch(async () => {
testData.value = await $axios.get('https://jsonplaceholder.typicode.com/users/1')
})
return {
testData
}
}
})
</script>
<style>
</style>
I've implemented a client-side request inside useEffect() per the documentation, and it works great when navigating inside the app, but if I load the page directly, it fails to return any data. I've checked that the user object is present, but somehow, it still always returns an empty set instead of the expected set of objects.
Dependencies:
{
"dependencies": {
"#supabase/auth-helpers-nextjs": "^0.2.8",
"#supabase/auth-helpers-react": "^0.2.4",
"#supabase/supabase-js": "^1.35.7",
"#supabase/ui": "^0.36.5",
"next": "12.3.1",
"pocketbase": "^0.7.1",
"react": "17.0.2",
"react-dom": "17.0.2"
},
}
pages/projects.tsx
import {GetServerSideProps, InferGetServerSidePropsType, NextPage} from 'next';
import styles from '../styles/Home.module.css';
import Footer from '../components/Footer';
import Header from '../components/Header';
import Meta from '../components/Meta';
import {useEffect, useState} from 'react';
import Link from 'next/link';
import {supabaseClient, withPageAuth} from '#supabase/auth-helpers-nextjs';
export const getServerSideProps: GetServerSideProps = withPageAuth({redirectTo: '/auth'});
const Projects: NextPage = ({user}: InferGetServerSidePropsType<typeof getServerSideProps>) => {
const [projects, setProjects] = useState<object | null>(null); // todo: Project types
const [isLoading, setLoading] = useState<boolean>(false);
useEffect(() => {
// fixme: works when navigating within the app, but not when the page is loaded from scratch
async function loadData() {
console.log({user});
const {data} = await supabaseClient.from('projects').select();
setLoading(false);
setProjects(data);
}
setLoading(true);
// Only run query once user is logged in.
// todo: error handling
if (user) loadData().then(() => console.log('Projects loaded', projects));
}, [user]);
return (
<div className={styles.container}>
<Meta titlePrefix={`Projects`} description={'todo'}></Meta>
<Header user={user} />
<main className={styles.main}>
<h1 className={styles.title}>Prioritizr Projects</h1>
<br /><br />
<div className={styles.grid3}>
{!projects && isLoading && <p className={styles.description}>Loading projects...</p>}
{
// #ts-ignore - todo: Project types
projects && projects.map(p => (<Link href={`projects/${p.id}`} key={p.id}>
<a className={styles.card}>
<h2 className={styles.solo}>{p.name}</h2>
</a>
</Link>))
}
{/* todo: module logic for handling partially-filled final row */}
</div>
<div className={styles.grid}>
<Link href='/new'>
<a className={styles.card}>
<h2>New Project →</h2>
<p>Need to prioritize a new set of things? Create a new project to get started on your own or with your
team.</p>
</a>
</Link>
</div>
</main>
<Footer />
</div>
);
};
export default Projects;
You can check isLoading state in addition to the user result before, since both of these states need to be resolved before you can fetch the data.
Adding both to the useEffect dependencies and to the if check should be enough.
Since you're using SSR, I'd recommend you fetch the data server-side in getServerSideProps like so:
export const getServerSideProps = withPageAuth({
redirectTo: '/',
async getServerSideProps(ctx) {
// Run queries with RLS on the server
const { data } = await supabaseClient.from('projects').select();
return { props: { data } };
}
});
Then you have the data available in your page props.
If you want to fetch the data client-side, you would have to use the useUser hook to get the user. This hook will let you know when the user is set on the client-side.
So I have a webapplication that is using axios to make endpoint request to my api that is on Swagger. In my app currently get and post calls work but not puts or deletes.
For my delete call I pass the userID into the ID field in the URL:
const onDelete = (userId) => {
axios.delete(`https://localhost:44373/api/Users/${userId}`)
.then(() => {
getData();
})
}
But in the console it shows the following two errors:
DELETE https://localhost:44373/api/Users/undefined 400 xhr.js:210
and:
Uncaught (in promise) Error: Request failed with status code 400
at createError (createError.js:16:1)
at settle (settle.js:17:1)
at XMLHttpRequest.onloadend (xhr.js:66:1)
This is my full "ReadUser" file:
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { Table } from 'react-bootstrap';
import { BrowserRouter as Router, Route } from 'react-router-dom'
import { Link } from 'react-router-dom';
export default function Read() {
const setData = (data) => {
let { userId, firstName, lastName, emailAddress, phoneNumber, password } = data;
localStorage.setItem('UserId', userId);
localStorage.setItem('First Name', firstName);
localStorage.setItem('Last Name', lastName);
localStorage.setItem('EmailAddress', emailAddress);
localStorage.setItem('Phonenumber', phoneNumber);
localStorage.setItem('Password', password)
}
const url = `https://localhost:44373/api/Users`;
const getData = () => {
axios.get(url)
.then((getData) => {
setAPIData(getData.data);
})
}
const onDelete = (userId) => {
axios.delete(`https://localhost:44373/api/Users/${userId}`)
.then(() => {
getData();
})
}
const [APIData, setAPIData] = useState([]);
useEffect(() => {
axios.get(`https://localhost:44373/api/Users`)
.then((response) => {
setAPIData(response.data);
})
}, [])
return (
<div>
<Table bordered>
<thead>
<tr>
<th key="firstName">First Name</th>
<th key="lastName">Last Name</th>
<th key="emailAddress">Emailaddress</th>
<th key="phoneNumber">Phonenumber</th>
<th>Update</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{APIData.map((data) => {
return (
<tr>
<td>{data.firstName}</td>
<td>{data.lastName}</td>
<td>{data.emailAddress}</td>
<td>{data.phoneNumber}</td>
<td><Link to='/UpdateUser'><td><button className="table-btn" onClick={() => setData(data)}>Update</button></td></Link></td>
<td>
<button className="table-btn" onClick={() => onDelete(data.id)}>Delete</button>
</td>
</tr>
)
})}
</tbody>
</Table>
</div>
)
}
Also I keep getting "Warning: Each child in a list should have a unique "key" prop."
But as far as I can tell I have added the correct keys? Thanks for any help!
You miss to add userId in axios.put request body. Example:
const updateAPIData = () => {
axios.put(`https://localhost:44373/api/Users/${userId}`, {
userId,
lastName,
emailAddress,
phoneNumber,
password
}).then(() => {
navigate('/ReadUser')
})
}
const onDelete = (userId) => {
axios.delete(`https://localhost:44373/api/Users/${userId}`, { data: { userId }})
.then(() => {
getData();
})
}
It's how to fix problem with keys in JSX:
{APIData.map((data, index) => {
return (
<tr key={index}>
....
<button className="table-btn" onClick={() => onDelete(data.userId)}>Delete</button>
It could be cors.
I had the same issue some time ago. Everything worked fine with postman but not with google chrome.
The problem comes from the fact that when sending methods other than get and post your browser will send a preflight request to make sure you are authorized to make the request.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
How to handle preflight CORS request using Node server?
For the unique key:
When you map an array, each element should have a unique key prop.
In your case your should have
<tr key={unique_key}>
The best practice would be to use the id of the element in your db for example:
<tr key={data.id}>
You could use the array index but it would be bad practice since it could change and introduce bugs in your application.
Today, I was playing around with GitHub API and I ran into the 60 calls per hour roadblock as described here - https://developer.github.com/v3/rate_limit/
For command line testing the solution is to use PAT - https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token
I am new learner but the GitHub doc was a little confusing so I had run around a lot. Github recommends the following CURL usage
curl -u GitHubUserName:personalaccesstoken https://api.github.com/users/GitHubUserName
but, then, using it in a fetch request is a challenge for there are a number of depreciation in the pipeline on how to use things.
So, the question, how best to get this working in a simple fetch call in node JS and React JS?
Eventually, I ended up with the following code block that gets it working.
import React, { useState, useEffect } from "react";
function GitHubUser({ login }) {
const [data, setData] = useState();
const [error, setError] = useState();
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!login) return;
setLoading(true);
fetch(`https://api.github.com/users/GitHubUserName`,{
method: "GET",
headers: {
Authorization: `token personalaccesstoken `
}
})
.then(data => data.json())
.then(setData)
.then(() => setLoading(false))
.catch(setError);
}, [login]);
if (loading) return <h1>loading...</h1>;
if (error)
return <pre>{JSON.stringify(error, null, 2)}</pre>;
if (!data) return null;
return (
<div className="githubUser">
<img
src={data.avatar_url}
alt={data.login}
style={{ width: 200 }}
/>
<div>
<h1>{data.login}</h1>
{data.name && <p>{data.name}</p>}
{data.location && <p>{data.location}</p>}
</div>
</div>
);
}
export default function App() {
return <GitHubUser login="GitHubUserName" />;
}
The main confusion was that in some parts of GitHub documentation it keeps saying we should use username, and basic and what not. Perhaps it was only confusion for me, but this solves it.
I am trying to connect my ASP.NET web services with React-Native app. I am using SQL Server with ASP.NET web services now want to connect react-native app with my ASP.NET - any solution for this?
Now I am stuck and searched a lot but I have not yet found any solution.
Here's the web service part. Let's say I'm just returning a corporate leader to the client. I can either create a Web API controller or an MVC controller that returns a JsonResult. leader here is merely a Leader c# object. I've chosen the latter. The key here is that we're returning JSON data back to the client in the form of a JSON object.
[HttpGet]
public JsonResult Leader() {
return Json(leader, JsonRequestBehavior.AllowGet);
}
Let's assume the endpoint of this service will be: http://www.example.com/Leader. Now my React Native app is going to need to reference this url There are various apis for retrieving data from a web service, but I like using Fetch or you could use Axios, etc. My example below will be using Fetch. For the most basic React Native app, we'd just using the componentDidMount() event to run the Fetch request, and put leader in a state object. Note: This is an oversimplified answer and I haven't tested it out.
import React, {Component} from 'react';
import { Text, Card } from 'react-native';
export default class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
leader = {},
errMessage = ''
}
}
componentDidMount() {
fetch(url)
.then(response => {
if (response.ok) {
return response;
} else {
let error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
let errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(leaders => {
this.setState({ leader: leader });
})
.catch(error => {
this.setState({ errMessage: error.message });
});
}
render () {
const {lastName, firstName} = this.state.leader;
return (
<Card
title="Our beloved leader">
<Text>`${firstName} ${lastName}/></Text>
</Card>
);
}
}
Your web service needs to return data in JSON format. You know which urls are defined for which actions.
Let's say you have an endpoint like: http://mywebservice.com/GetEmployees.
In your React app, you're going to run XMLHttpRequest or Fetch using those web service urls, such as http://mywebservice.com/GetEmployees. You will process the returned JSON in your React App and display it with something like the JavaScript map function.
As the others have mentioned, your web service is going to be talking to SQL Server. Your React Native app will not be dealing directly the SQL Server.
class EwdsUserBox extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
loadCommentsFromServer(page=0, count=25) {
const xhr = new XMLHttpRequest();
let params = "?page="+page+"&count=" + count;
xhr.open('get', this.props.url, true);
xhr.onload = function() {
var data = JSON.parse(xhr.responseText);
this.setState({ data: data});
}.bind(this);
xhr.send();
}
componentDidMount() {
this.loadCommentsFromServer(0,25);
}
render() {
const ewds = this.state.data;
var count = 0;
return (
<div className="ewdsUserBox body-content">
<EwdsUserSummary total={ewds.length} disabled={count} locked={0}/>
<EwdsUserTable data={ewds} />
</div>
);
}
}
This is for ReactJS but you'll notice I'm using an XMLHttpRequest to retrieve the JSON data. EwdsUserBox is just my container component. I'll then pass this data to subcomponents, in this case a user table and user row.
const EwdsUserTable = (props) => {
let counter = 0;
let ewdsData = props.data;
if (ewdsData) {
var ewdsUserRows = ewdsData.map(function (ewdsUser) {
return (
<EwdsUserRow ewdsUser={ewdsUser} key={counter++} />
);
});
}
return (
<div className="ewdsUserTable" >
<table id="mytable" className="table table-striped table-bordered table-condensed fixed">
<caption>EWDS Users</caption>
<thead>
<tr>
<th className="sort" type="string">User Name</th>
<th className="sort" type="string">Email Address</th>
<th>Pwd Changed</th>
<th type="date">Last Logon</th>
<th>Locked</th>
<th className="sort" type="string">Disabled</th>
<th></th>
</tr>
</thead>
<tbody>
{ewdsUserRows}
</tbody>
</table>
</div>
);
};
Here's where I'm actually displaying the data.
class EwdsUserRow extends React.Component {
render() {
const {UserName, EmailAddress, AccountCreated, PasswordChanged, AccountName,
Locked, Enabled} = this.props.ewdsUser;
return (
<tr>
<td>{UserName}</td>
<td>{EmailAddress}</td>
<td>{AccountCreated}</td>
<td>{PasswordChanged}</td>
<td>{Locked}</td>
<td>{Enabled}</td>
</tr>
);
}
}
I created my services on Node.js and then I run my services with a specific IP Address and I used this IP address in my application to get data from Database using webservices of Node.js.