Remix loader returning "undefined" - reactjs

I am giving remix a good first-time try and I think I love its approach to data handling. However, I am facing an issue with data returning "undefined" from the loader wrapper.
import { LoaderFunction } from "#remix-run/node";
import { useLoaderData } from "#remix-run/react";
import axios from 'axios';
const url = 'https://jsonplaceholder.typicode.com/users'
export async function Members(){
const {data} = await axios.get(url);
return data
} //I am sure it returns the expected data when I call on this function.
export const loader: LoaderFunction = async () => {
const response = await Members()
return response
};
export const Architects = () => {
const members = useLoaderData()
console.log(members)
return (
....
)
}
What am I really missing here? I'll appreciate a pointer here. It wouldn't be wise to use other react based approaches that isn't remix's

This isn't even an issue but a misappropriation in writing the methods.
For anyone who might make this kind of silly mistake, please, do ensure you are calling these remix helpers in your ROUTES.
It will not work in any of your components files just like I tried to do it.
The loader and useLoaderData and most of the remix's methods are mostly serverside. Nothing is wrong with the above code. Where I called it is what the problem was.
Thanks to all those who viewed this.

I would also like to point out that LoaderFunction should be imported like this:
import type { LoaderFunction } from "#remix-run/node";

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.

Is it possible to use i18n localization for redux Actions?

I was trying to implement i18n localization for Redux Action functions, but i constantly recieve different hook errors. When i implemented i18n this way i recieve error.
Line 428:17: React Hook "useTranslation" is called in function "sendDataRequest" that is neither a React function component nor a custom React Hook function.
import { useTranslation } from "react-i18next";
export const sendDataRequest = (requestId) => {
const { t } = useTranslation();
return async (dispatch) => {
try {
dispatch(sendDataRequest());
await dataAPI.sendDataRequest({ requestId });
notification.success({
message: t('infoPage.requestSentSuccessfully'),
});
dispatch(sendDataSuccess());
} catch (error) {
dispatch(sendDataFailure());
console.error(error);
}
}
}
Then i moved const { t } = useTranslation(); inside of return statement.
But then i recieved another error
It looks like I obviously using it wrong here.
But i cannot find any examples on i18n being used in Actions.
Does anyone knows is it even possible to use i18b in Actions?
Check out https://github.com/i18next/react-i18next/issues/909
You need to gain access to your i18next instance. The one you create somewhere in your codebase. With this instance you can simply call i18n.t("my.translation.key") to translate. This is completely independent from react.

What is the correct way to pass parameters to a React-query useQuery method that uses Axios

I am currently building a Ruby on Rails Webpacker application with a React front end. I am at the point where I would like to create all the quires I need to make calls to my Rails API. I was loosely following this tutorial https://www.youtube.com/watch?v=0bKc_ch6MZY (https://github.com/daryanka/react-query-tutorial/blob/master/src/containers/Post.js, https://github.com/daryanka/react-query-tutorial/blob/master/src/Queries.js), in order to write some axios based query functions that I could use with react-query. I had no problem with getting the queries to behave as expected when the url for the endpoint was a hard coded string. When I attempted to pass in a parameter to make dynamic urls I ran into the issue of not having access to said parameter; specifically the "prodId" parameter. I did however notice that the "prodId" was inside the "key" parameter array like so:
queryKey: Array(2)
0: "product"
1: "1"
length: 2
enter code here
I could just access it from there but that approach does seem a little off, I also did not find any examples or documentation that attempted to access a parameter from the query key array. I would like to know what it is I am doing incorrectly with regards to passing in parameters? Were there some syntax changes in react-query that I am not taking into account?
react-query#^3.17.2
webpacker (5.2.1)
axios#^0.21.1
//Product.js
import axios from "axios"
import { getProduct } from "../../queries/products"
import { useQuery } from "react-query"
const prodId= '1'
const { data } = useQuery(['product', prodId], getProduct)
//queries/products.js
import axios from 'axios'
export const getProduct = async (key, { prodId }) => {
console.log(opid)
const { data } = await axios.get(`/api/v1/products/${prodId}`)
return data
}
The query function that you pass to react-query gets a queryContext injected, which is an object that consists of the queryKey (and some more information if you are using an infinite query). So yes, one correct way to access dependencies is through the queryKey:
export const getProduct = async ({ queryKey }) => {
const [_, prodId] = queryKey
const { data } = await axios.get(`/api/v1/products/${prodId}`)
return data
}
const { data } = useQuery(['product', prodId], getProduct)
Another way is to use inline anonymous functions, which is well documented in the docs in: If your query function depends on a variable, include it in your query key
export const getProduct = async (prodId) => {
const { data } = await axios.get(`/api/v1/products/${prodId}`)
return data
}
const { data } = useQuery(['product', prodId], () => getProduct(prodId))
I'm using the following (typescript) to send parameters to my custom useQuery hook.
import { useQuery } from 'react-query'
import service from '../api'
const queryKey = 'my-query-key'
type useProductsParams = Parameters<typeof service.listProducts>
const useProducts = (...params: useProductsParams) => {
return useQuery(queryKey, () => service.getProduct(...params))
}
export default useProducts

Why is fetching data in next.js with hardcoded api-key working but not with environment variable?

I followed the documentation of Next.js, so I created a file called .env.local and stored my API key inside.
When console.logging that key it gets shown in the server-console and not in the browser console. So far I understand this.
Problem: I want to fetch some data from the given URL. How can I get this done, without giving my API_KEY to the browser?
I think that topic is quite confusing for beginners (as me) and I an many other (so I think) would be overjoyed if anyone could get the confusion out of that.
Here is my code: (If I hardcode my API_KEY inside the URL it works fine)
import Haversine from '../components/Haversine'
import LangLat from '../components/LangLat'
import axios from 'axios'
import { useEffect } from 'react'
const key = process.env.API_KEY
const index = () => {
console.log(key)
const getLangLat = async () => {
try {
const response = await axios.get(
`https://geocode.search.hereapi.com/v1/geocode?q=wimpfener str 40 backnang&apiKey=${key}`
)
console.log(response.data)
} catch (err) {
console.error(err.message)
}
}
useEffect(() => {
getLangLat()
})
return (
<div>
<Haversine />
<LangLat />
</div>
)
}
export default index
You need to add NEXT_PUBLIC_ to the beginning of your environmental variable so you have access to it on the client side.
So inside of your .env.local change
API_KEY to NEXT_PUBLIC_API_KEY and do the same inside of your code.
https://nextjs.org/docs/basic-features/environment-variables#loading-environment-variables

useRouter not working inside getInitialProps

I am trying to get data from the API by using POST Method, However, I am struggling to set the data into post
import { useRouter } from 'next/router';
import Layout from '../../components/MyLayout';
import Settings from '../../components/Settings';
const Post = props =>{
//works if I use here
const router = useRouter();
return (
<Layout>
<h1>{router.query.id}</h1>
<p>This is the blog post content.</p>
</Layout>
);
}
export default Post;
Post.getInitialProps = async function(){
//trying to get data ($_GET)
const router = useRouter();
const data = router.query;
//
const FormData = new URLSearchParams();
const res = await fetch(Settings.api+'viewPost',{
method: 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded',
},
body: FormData,
});
const obj = await res.json();
return(
obj
);
}
I receive this following error
Invalid hook call. Hooks can only be called inside of the body of a
function component. This could happen for one of the following
reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app See *** for tips about how to debug and
fix this problem.
I just learn about this, sorry for the dumb question. I really appreciate any answer. Thank you.
I did the exact same thing (try to use useRouter in getinitialProps) as you and get the same error just now, then I search around and found how to get query string parameter in next , so to answer your question , you don't need useRouter in this case but instead use getInitialProps (props) and find the query params to get your data or Id or whatever. Hope that helps.
Post.getInitialProps = async function({ query }){
const { data } = query;
...................
}

Resources