intergation of flask for ML into a meteor.js app - reactjs

I have build a simple pure react and meteor web app. I am trying to connect a flask API to my meteor.js app for the machine learning component of my application. I have seen examples for pure react front end but cant get the same logic to work for meteor.
what I did is:
make a flask app and return the prediction results to localhost:5000 as a python dictionary e.g.
{'class': 'bird', 'confidence':'0.8932'}
Set up a proxy in my meteor app in package.json, I have meteor app running at localhost:3000:
"proxy":"http://127.0.0.1:5000/"
finally, this is where I am confused, I have a bunch of components in my home page, I am not sure if I have to render the flask results in a component or page, nor how to do that. What I tried Is to render the results in one of the components using the useEffect, useState functions.
I get an error that says something like I can't use this funtionality.
function App() {
const [predictedClass, setPredictedClass] = useState(0);
useEffect(() => {
fetch('/prediction').then(res => res.json()).then(data => {
setPredictedClass(data.class);
});
}, []);

I use the useEffect method to get the data from the requests of my api.
example:
const [data, setData] = useState(null);
useEffect(() => {
getData('GET', '/api/test')
.then(response => {
setData(response)
})
.catch(error =>
console.log(error)
);
}, []);
Where getData is a custom function that calls an axios request.

Related

React Query does not work with Astro Framework

I'm trying to use React-Query with Astro to fetch data from my Django Rest Framework backend. Astro has been a great way to organize my react-based frontend but I am worried it might not be compatible with React-Query.
Whenever I try to make a query to my backend I get an 'isLoading' value of true (and an isError of false). I never manage to recover the data from my endpoints however.
I have been following a variety of tutorials with the same results. Here is the code where I'm stuck:
import { QueryClient, useQueryClient, QueryClientProvider, useQuery } from '#tanstack/react-query';
import { gettestApi } from "../../api/testApi";
function MyComponent(props) {
const queryClient = useQueryClient();
const {
isLoading,
isError,
error,
data: test
} = useQuery('test', gettestApi)
let content
if (isLoading) {
content = <p>Loading...</p>
} else if (isError){
content = <p>{error.message}</p>
} else {
content = JSON.stringify(test)
}
As you can see, I import an axios function from /api/testAPI.js which looks like this:
import axios from "axios"
const testApi = axios.create({
baseURL: "http://127.0.0.1:8000"
})
export const gettestApi = async () => {
return await testApi.get("/api/endpoint/").then(response => response.data)
}
That's how most tutorials I have seen and the official documentation wrap up their examples, however my backend server which should be triggered by this endpoint records absolutely no hits from react-query, which is curious to me. I understand that nothing 'calls' my react-query or my gettestApi() function, but it seems to be unnecessary for other people to retrieve their data.
Maybe it would be useful to point out that contrary to other framework with React, Astro does not have an App.js root to surround with
<QueryClientProvider client={client}>
<App />
</QueryClientProvider>
Instead, I have added these QueryClientProvider brackets to the highest React component I could.
I feel like I'm missing some intuition about Tanstack Query/ React-Query. Could anybody point me in the right direction? Thanks a lot for the help.
From what I've seen in the astro docs:
The most important thing to know about Astro components is that they render to HTML during your build. Even if you run JavaScript code inside of your components, it will all run ahead of time, stripped from the final page that you send to your users. The result is a faster site, with zero JavaScript footprint added by default.
So it seems all react code only runs on the server, where data fetching via useEffect or useSyncExternalStore subscriptions just doesn't run. But this is exactly what react-query is doing, so yeah I think they don't work well together. I'm also not sure what the purpose of react-query in a setting would be where there is no client side javascript.
You can set client:only on your Astro component so the React component doesn't run on the server. There are shared-state limitations but still React Query feels better than just fetch + useEffect + own-code even if its not in a complete React app. In this example I'm also using an init function that reads cookies from the client's browser which is another case for when to use client:only.
Astro:
---
import Layout from "../../layouts/Layout.astro";
import ClientPanel from "../../components/client/ClientPanel";
---
<Layout title={ 'Client' }>
<ClientPanel client:only></ClientPanel>
</Layout>
React:
// imports
const queryClient = new QueryClient()
/** client:only component */
const ClientPanel = () => (
<QueryClientProvider client={queryClient}>
<ClientData />
</QueryClientProvider>
)
const ClientData = () => {
const { getUser, getSession } = useSession(); // read cookies functions
const [ user, setUser ] = useState(getUser);
const { isLoading, error, data } = useQuery({
queryKey: ['patientData'],
queryFn: () => getSession() // validate or refresh token
.then(session => fetchPatientData(session.tokens.token))
.catch(error => error === 'INVALID_SESSION' ? null : undefined)
})
if (!user || data === null) window.location.replace('/login')
// return statement, etc.

Module federation - SSR data fetching on remote module

The problem: I am trying to set up a simple module-federation enabled React application that uses server-side rendering.
There is a host application hostServer. It consumes a remote component called SharedComponent, which is served by another application called remoteServer.
I want the SharedComponent to do some data fetching and have the results be part of the initial server render.
The code: I am starting with Zack Jackson's SSR example here:
https://github.com/module-federation/module-federation-examples/tree/master/server-side-render-only
It does all I need minus the data fetching.
What I've tried: Modifying the SharedComponent.js along the lines of the following - which I know won't work, but I couldn't think of anything else.
import React from 'react';
import fetch from 'node-fetch';
const SharedComponent = () => {
const [data, setData] = React.useState([])
async function getData(){
const data = await fetch('https://swapi.dev/api/planets')
const json = await data.json();
setData(json)
}
React.useEffect(() => {
getData()
}, [])
return (
<>
<div>Shared Component2222</div>
<p>Data; {JSON.stringify(data)}</p>
</>
);
}
export default SharedComponent;
Result: As expected, the data fetching happens client side rather than server side.
How can I get SharedComponent to do server-side data fetching?

Axios get request from local server url from within React app

I have a Typescript Express server with an API route that also serves a Typescript React app on the domain root.
E.g.
https://myapp.test returns the React Web App
https://myapp.test/api/message returns some message string
Inside of the React app, I'm using axios to sent a GET request to the API route and obtain the message:
function App() {
const [data, setData] = useState("");
useEffect( () => {
( async () => {
const message = (await axios("http://localhost:8000/api/message")).data as string;
setData(message);
})();
}, []);
return (
<div>Message is: {data}</div>
);
}
Can I supply the request URL as one relative to the current URL? For example, something like "/api/message". If not, how should I be configuring React so that it can reliably know the API url, regardless of where it is deployed (e.g. Heroku)?
const message = (await
axios(window.location.host+"/api/message")).data as string;

Calling API via redux in react app does not work

I am building a web app with MERN stack and using redux as the state management. I am now trying to load the data from mongoDB with my API and storing into redux before setting into react state. When calling the api with getShop() function directly from react app, the data is stored in react state and displayed in the app. However it does not work when i am trying to use it through redux as per my below codes. There are no errors, but just not loading any information.
Action:
load : () => {
let thunk = (dispatch) => {
api.getShops()
.then(res => {
let barbershops = res.data
dispatch(barberFactory.set(barbershops))
})
}
return thunk
},
calling from react app:
function mapDispatchToProps(dispatch){
return {
loadBarber : () => {
dispatch(barberFactory.load)
},
}
}
The function is called at componentDidMount()
Your load function needs to be called in order to return the inner action i.e.
dispatch(barberFactory.load())

Using Jest Mock API Calls to SetState

I have an API call which runs whenever a certain component mounts. If this API call is successful the response data is used to update the state of one of my React Hooks.
The issue I am having is either related to asynchronicity or a poorly formatted mock API call, but no matter what I try I cannot get this test to work.
Here is a simplified version of the API:
const getOrg =() => {
axios.get(URL, config)
.then(response => response.data)
.then(data => {
setOrgTitle(data.name)
}
}
Basically the API is triggered and my setOrgTitle hook is updated from the response.
const [orgTitle, setOrgTitle] = useState("");
Now in my return statement I am displaying the value of orgTitle:
<h1 className={styles.titleText} id="document-folders-h1">
{orgTitle} Folders
</h1>
Alright, so the component is pretty simple. When I am trying to test things my two ideas were to either set the initial orgTitle hook state in my test or to mock the API. After some research I decided mocking the API was the way to go.
So I have a mockAxios component:
const mockAxios = {
get: jest.fn(() => Promise.resolve({ data: {} }))
};
module.exports = mockAxios;
And my test file:
import mockAxios from "../../mockTests/DocumentFoldersMock";
it("fetches results for getAdminOrg", () => {
axios.get.mockImplementation(() =>
Promise.resolve({ data: { name: "GETtest" } })
);
const wrapper = mount(
<AppProviders>
<DocumentFolders />
</AppProviders>
);
const orgTitle = wrapper.find("#document-folders-h1");
expect(orgTitle.text()).toContain("GETtest Folders");
});
I am mocking the response data, however I am not sure how to run the setOrgTitle function which is called in the .then of my actual axios call. How can I do this from my mock axios call using my mock response?
The result of the Jest test says expected("GETtest Folders") received(" Folders") so I am pretty sure that I am either having an issue with asynchronicity or an issue calling the hook update.

Resources