Getting correct ID without sharing URL - mysql

I have an Angular 4 application where I am trying to fetch a single row (using ID) from a MySQL database. I am using NodeJS with ExpressJS. However, I am struggling finding a way to get the ID from the URL without sharing the exact URL-path, as that would lead to the website only rendering the JSON-object, and not the components.
server.js
app.get('api/books/:id', (req, res) => {
console.log(req.params.id);
});
If the URL is localhost:3000/books/3, the console will log :id. localhost:3000/api/books/3 will however log the correct ID to the console. The issue is that using the latter as my URL in my Angular routing will result in a shared path, which will not work.
Here's an example of how I use Angular's HttpModule to send a GET-request to the server:
this.http.get('api/books/:id')
.map(res => res.json())
.subscribe(data => {
this.bookDetail = data;
});
Here is my path from the routing using Angular's RouterModule:
{ path: 'books/:id', component: BookDetailComponent }
How would I go about solving this issue?

You need to create a function that on the init of that component, the angular app triggers the HTTP request to the server. for example, I have a blog application.
{ path: 'blogs/:id', component: BlogComponent },
ngOnInit() {
this.route.params.subscribe(params => this.blog = params.id);
this.getBlog(this.blog);}
getBlog(blog) {
this.blogService.getBlog(blog).subscribe(
data => { this.foundBlog = data;
if (data.comments) {
this.comments = data.comments;
}
getBlog(blog): Observable<any> {
return this.http.get(`http://localhost:3000/api/blogs/${blog}`).map(res => res.json());
}
the first is my route, the second is the init function on my blog component
the third is the get blog function on the blog component
the last is the get blog function on my blogservice, that send the HTTP request
hopefully that helps.

Related

I can't fill a request response using axios in state variable in React.js with Next.js

I'm working with React.js and I have the following problem:
import axios from "axios";
export default function Home() {
const [products, setProducts] = useState([]);
const ax = axios.create({ headers: { Accept: 'application/json' }});
function test() {
const res = ax.get("https://vtexstore.codeby.com.br/api/catalog_system/pub/products/search").then((response) => {
// expected the setProducts to be filled with the return of this request
setProducts(response.data);
});
}
test();
// and when I get here to see if the products have been filled, I get an empty array [ ]
console.log(products);
/*
as the products variable was not filled within the axios promise by setProducts,
there is no way to throw the products array here in the HTML to make a forEach or
a map to look cute together with the tags
*/
return (
<sup>how sad, with the product array empty, I can't put the data here '-'</sup>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
See how the result comes out in the IDE console:
I'm in Visual Studio not knowing what to do, I'm new to ReactJS with NextJS and from an early age I've been trying to see if I could solve this problem, but without success.
What can I do to bring the products to the HTML page?
UPDATE: As per the solution below, I created a possible workaround that indicates a path that could have returned a solution
ax.get("https://vtexstore.codeby.com.br/api/catalog_system/pub/products/search/", {})
.then((response) => setProducts(response.data))
.catch((error) => {
console.log(error); // AxiosError {message: 'Network Error', name: 'AxiosError', ...}
console.log(error.status); // undefined
console.log(error.code); // ERR_NETWORK
});
useEffect(() => {
console.log(products);
}, []);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.0.2/umd/react-dom.production.min.js"></script>
and I'm getting the same error that I put in the comments of the first answer below:
but when I change the setProducts by the console.log to see if it returns the same result, this appears in the terminal where my next.js application is running
that:
ax.get("https://vtexstore.codeby.com.br/api/catalog_system/pub/products/search/", {})
.then((response) => console.log(response.data.length)) // returns the length of the products array
returns this when I update my app:
NOTE: That's why I'm not able to understand my application in Next.js. I'm following all the correct guidelines, writing the code perfectly using axios and when I run the application on the website it gives a network error and doesn't show exactly the amount of products that were displayed in the terminal where my application is running.
I've already configured all the request headers correctly, enabling CORS to allow external requests with other API's, and I still don't succeed in returning the data to my application's page.
Wrap the stuff you have to fetch products inside useEffect hook
useEffect(()=>{
const ax = axios.create({ headers: { Accept: 'application/json' }});
function test() {
const res = ax.get("https://vtexstore.codeby.com.br/api/catalog_system/pub/products/search").then((response) => {
// expected the setProducts to be filled with the return of this request
setProducts(response.data);
console.log(response.data)
});
}
test();
},[])
Then in your return of the component, you can use map on products array with null and undefined checks
Like
{products && products.map(product=>{})}

Is it possible to perform an action with `context` on the init of the app?

I'm simply looking for something like this
app.on('init', async context => {
...
})
Basically I just need to make to calls to the github API, but I'm not sure there is a way to do it without using the API client inside the Context object.
I ended up using probot-scheduler
const createScheduler = require('probot-scheduler')
module.exports = app => {
createScheduler(app, {
delay: false
})
robot.on('schedule.repository', context => {
// this is called on startup and can access context
})
}
I tried probot-scheduler but it didn't exist - perhaps removed in an update?
In any case, I managed to do it after lots of digging by using the actual app object - it's .auth() method returns a promise containing the GitHubAPI interface:
https://probot.github.io/api/latest/classes/application.html#auth
module.exports = app => {
router.get('/hello-world', async (req, res) => {
const github = await app.auth();
const result = await github.repos.listForOrg({'org':'org name});
console.log(result);
})
}
.auth() takes the ID of the installation if you wish to access private data. If called empty, the client will can only retrieve public data.
You can get the installation ID by calling .auth() without paramaters, and then listInstallations():
const github = await app.auth();
const result = github.apps.listInstallations();
console.log(result);
You get an array including IDs that you can in .auth().

React Fetch: Getting json result but showing network error

I spent the day setting up ssl on my local machine. I am running a wamp stack to build an api locally for testing. This endpoint is set up for ssl now and works perfect. I have a simple route setup that returns a json response.
https://localhost/api/test
It works via firefox by visiting that address.
Now, I am running a react app on
localhost:3000
The problem I am having is that I am trying out the fetch() api and using an example found on the react site (https://reactjs.org/docs/faq-ajax.html). Here is the code but it's extremely simple.
import React, { Component } from "react";
class Api extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
fetch("https://localhost/api/test")
.then(res => res.json())
.then(
result => {
this.setState({
isLoaded: true,
items: result.items
});
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
error => {
this.setState({
isLoaded: true,
error
});
}
);
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<ul>
{items.map(item => (
<li key={item.name}>
{item.name} {item.price}
</li>
))}
</ul>
);
}
}
}
export default Api;
The kicker is, if I look at the console, I am getting a 200 response code from the request and also the actual JSON response with the proper data....yet for some reason in the app it is printing NetworkError when attempting to fetch resource.
I would understand the error if it wasn't getting the proper response or code but this just doesn't make sense.
Any advice would be helpful and appreciated!
Well, it looks like it was a CORS issue...which I didn't think would be a problem since everything is local. I had to add the following to my Flight Api backend.
Flight::before('json', function () {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET,PUT,POST,DELETE');
header('Access-Control-Allow-Headers: Content-Type');
});
You have to make sure that CORS is enabled in your HTTP headers which you can do from server side and for client side you have to just write mode:'cors' in your fetch api call, because the server would throw an error and your browser would not be able to load the content served for the requested client.

Get past request without waiting for response (Angular 2 +)

I am looking for data in an API via Get request, I need the data inside my OnInit to use in composing other data. The problem is that the method is being called but it is as an async method (without await), it passes everywhere but when the return is obtained the excution of the main method has already been finished with no results. I tried the implementation of asynchronous methods but it did not solve.
service:
getObjects(): MyClass[] {
let objects = new Array<MyClass>();
this.obterTodos<MyClass>(this.uriApi)
.map(res => res.map(x => new MyClass(x.Description, x.Id)))
.subscribe(entities => {
objects = entities;
});
return objects ;
}
get request
public getObjects<TEntity>(url: string): Observable<TEntity[]> {
return this.httpService
.get(this.serviceUrl + url, this.options)
.map(res => res.json())
.catch(this.handleError);
}
component:
ngOnInit() {
this.myObjects= this.setorService.obterSetores();
console.log('this.myObjects is empty here');
}
so you'll want to subscribe to your observable in the component. This is typically done so the component can determine when the http request should be ran & so the component can wait for the http request to finish (and follow with some logic).
// subscribe to observable somewhere in your component (like ngOnInit)
this.setorService.obterSetores().subscribe(
res => {
this.myObjects = res;
},
err => {}
)
now the component knows when the http request finishes

ionic 2 http service get data local json file

I have a ionic 2 small application that uses a local json file stored in the assets folder. This file provides bio data on historical people and so does not need to be edited in anyway. I can access the file in the home.ts like so
constructor(public navCtrl: NavController, public http: Http) {
this.http.get('../assets/people.json').subscribe(data => {
this.people = data.json();
});
Note this works and I can loop through the data via the *ngFor loop.
But I think this should go into a service. But I can't work out how to put this into a service and then access the data in my home pages. I searched around but can not find any solution.
I was able to do this thanks to this tutorial from TutorialsPoint. The tutorial demonstrates how to create a service, and I combined the instructions with ionic Storage to set and get data from a file stored locally.
export class SomeService {
...
getSomething(): Observable<Something[]> {
return this._http.get(this._someUrl)
.map((response: Response) => <Something[]> response.json())
.do(data => this.storage.set("some_key", data));
}
...
}
Service.js
return this.http
.request('assets/data/radio-stations.json')
.map(response => response.json());
contoller.js
this.service.getdata()
.subscribe(response => {
this.data = response.Radios;
}, err => {
console.log(err);
});