I got the below errors while building my application. Not sure why this is happening. I wrote a fetch in a sperate function and my trying to call my fetch function (that is styled as a custom react hook) in my getStaticSite props but it is not letting me. How can I bypass this problem? I don't think I'd have this problem if I just wrote the fetch directly into the getStaticSite props, but for organizational reasons I prefer to write my fetches in functions.
The Error I get:
./pages/SSG/paristimeisg.js
6:22 Error: React Hook "useFetchParisTimeISG" is called in function "getStaticProps" that is neither a React
function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use". react-hooks/rules-of-hooks
useFetchParisTimeISG code below
import React from "react";
export default async function useFetchParisTimeISG() {
const response = await fetch(
`https://timeapi.io/api/Time/current/zone?timeZone=Europe/Paris`
);
const currenttimeinparis = await response.json();
return currenttimeinparis;
}
paristimeisg page code below.
import useFetchParisTimeISG from "../../hooks/SSR/ISR/useFetchParisTimeISG";
export async function getStaticProps() {
let mytime = await useFetchParisTimeISG();
return { props: { mytime }, revalidate: 60 };
}
export default function paristimeisg({ mytime }) {
console.log("This is my time", mytime);
return (
<div>
Hello
<h2>{mytime.milliSeconds}</h2>
</div>
);
}
Extra question
I get the same error listed as the above for this page, despite not having any react hooks inside non react components(unless I am missing something?).
Error I get:
./pages/SSG/timeforISG.js
5:16 Error: React Hook "useFetchParisTimeISG" is called in function "timeforISG" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use". react-hooks/rules-of-hooks
Page code
import React from "react";
import useFetchParisTimeISG from "../../hooks/SSR/ISR/useFetchParisTimeISG";
export default function timeforISG() {
let mytime = useFetchParisTimeISG();
return <div>{mytime}</div>;
}
useFetchParisTimeISG code is the same as above (top of page).
Your issue is a simple one - you are incorrectly trying to use a React Hook in a non-React component (getStaticProps, which is a NextJS function).
The solution is simple:
Create a plain old JavaScript file that is not named like a Hook (e.g. parisTimeFetcher.js)
Paste in your original code (with a function name change to avoid a possible React error over the "use" syntax, and remove the React import as it is just plain JavaScript):
export default async function fetchParisTimeISG() {
const response = await fetch(
`https://timeapi.io/api/Time/current/zone?timeZone=Europe/Paris`
);
const currenttimeinparis = await response.json();
return currenttimeinparis;
}
Now, import the function into your Next page, and use this function inside getStaticProps:
import { fetchParisTimeISG } from "../../fetchers/parisTimeFetcher";
export async function getStaticProps() {
let mytime = await fetchParisTimeISG();
return { props: { mytime }, revalidate: 60 };
}
Giving your naming that is prefixed with use, React assumes that you're trying to call a hook with its manageable state outside of a component (which it will not work) thats why it throws this error.
Hooks shouldn't be called inside a regular functions as mentionned in react official Doc
You should change your naming and remove the use Prefix (You dont have to remove it from the the file name but its recommended)
Related
I'm getting the error below.
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:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See (link I couldn't add) for tips about how to debug and fix this problem.
You might have mismatching versions of React and the renderer (such as React DOM)
Here is my code. Is it breaking rules of hooks or is the issue something else?
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useData } from 'useData';
export const checkReference = ({
refId,
}) => {
const data = useData(); //useContext hook
let refData = {};
if (refId) refData = data.getReference(refId);
useEffect(() => {
console.log('INITIAL LOGIC');
if (refData.parameter){
console.log('SECONDARY LOGIC', refData);
}
}, [])
checkReference.propTypes = {
refId: PropTypes.string,
}
checkReference.defaultProps = {
refId: null,
}
}
I am calling it from another file using
checkReference('page-name');
I've got the same issue in my Next.js app. It was a cache related issue. you can try these steps.
Delete node_modules and .next folders
Run npm install or yarn
Start your project again
React hooks are intended to be used inside Functional components like:
export const CustomComponent = () => {}
export function CustomComponent() {}
They cannot be used in normal function because it won't exist inside the context of a React component. If you want to use things like useState or useEffect inside functions defined outside a component, you have to create a custom hook. That is, create a function with the use prefix (e.g. useCheckReference) and then use it like:
export const MyComponent = () => {
const reference = useCheckReference()
}
In that way React knows that that function is presumably gonna be called inside a component and the use of hooks is reliable, also is going to make some optimizations related to hooks and components life cycle.
Trying out Next.js but I'm struggling with the following. Just tried to install react-hook-mousetrap and imported it like I normally would:
import useMousetrap from "react-hook-mousetrap";
This gives me the following error:
SyntaxError: Cannot use import statement outside a module
1 > module.exports = require("react-hook-mousetrap");
I am not sure what this means? I then thought it might be a problem with Nextjs's SSR, since my library enables hotkeys and will use some browser APIs. If you already know that I am on the wrong track here you can stop reading now.
What I did next however was this, I tried dynamic imports:
1. Dynamic import with next/dynamic
First thing I came across was next/dynamic, but this seems to be for JSX / React Components only (correct me if I'm wrong). Here I will be importing and using a React hook.
2. Dynamic import with await (...).default
So I tried dynamically importing it as a module, but I'm not sure how to do this exactly.
I need to use my hook at the top level of my component, can't make that Component async and now don't know what to do?
const MyComponent = () => {
// (1) TRIED THIS:
const useMousetrap = await import("react-hook-mousetrap").default;
//can't use the hook here since my Component is not async; Can't make the Component async, since this breaks stuff
// (2) TRIED THIS:
(async () => {
const useMousetrap = (await import("react-hook-mousetrap")).default;
// in this async function i can't use the hook, because it needs to be called at the top level.
})()
//....
}
Any advice here would be appreciated!
The error occurs because react-hook-mousetrap is exported as an ESM library. You can have Next.js transpile it using next-transpile-modules in your next.config.js.
const withTM = require('next-transpile-modules')(['react-hook-mousetrap']);
module.exports = withTM({ /* Your Next.js config */});
I don't know if my answer is actual, but i'm facing whith this problem today, and what that i done:
//test component for modal
const Button: React.FC<{close?: () => void}> = ({ close }) => (
<React.Fragment>
<button type="button" onClick={ close }>Close</button>
</React.Fragment>
);
// async call import react custom hook in next js whithout a dynamic
//import
let newHook;
(async () => {
const { hookFromNodeModules } =
await import('path/to/hook');
newHook = hookFromNodeModules;
})();
export default function Home() {
// check if hook is available
const openModal = newHook && newHook();
const { t } = useTranslation('common');
// useCallback for update call function when hook is available
const handleOpen = React.useCallback(() => {
openModal?.openModal(Button, {});
}, [openModal]);
return ( ...your code )
}
hope this help!)
screen from next.js app
After a post request to an external API, I would like to redirect back to the homepage. I do have some knowledge with React and this is my first time using Next.js. Here is the code:
export default function New({genres}) {
const createMovie = (values) => {
console.log(values);
axios.post(`${process.env.NEXT_PUBLIC_BASE_URL}/movies`, {
title: values.title,
description: values.description,
genres: values.genres,
release_date: values.release_date,
cover_url: values.cover_url
}).then(res => {
const router = useRouter();
router.push('/');
})
}
As you can see I used router.push() but I get this error:
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:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
What is the most efficient way to redirect to other pages in Next.js after a function and/or requests?
You need to move where you call useRouter(). You can keep router.push() where it is.
export default function New({genres}) {
const router = useRouter();
const createMovie = (values) => {...}
}
If you look at the Rules of Hooks, you can only call the hook, useRouter() in this case, at the top level.
I also had my initialization of useRouter in my function. I fixed the same bug by placing that line into my function component instead of my function and calling router.push(...) in the function itself.
I have this custom hook to get the current user from firebase:
import React, { Component, useEffect, useState } from 'react';
import { auth } from "../firebase/auth-service"
const useFirebaseAuthentication = (firebase) => {
const [authUser, setAuthUser] = useState(null);
try {
auth.onAuthStateChanged(async user => {
if (user) {
setAuthUser(user)
} else {
setAuthUser(null);
}
})
} catch (error) {
throw error
}
return authUser
}
export default useFirebaseAuthentication;
When I print on the screen the current user from this custom hook - I get the result as expected.
When I use the hook and try to get the user - I get null.
Can someone point out my mistake?
I don't think that useState here is appropriate, don't you get any console warnings? A hook is just a js function as any other, it's not a React component!
Try to use a local variable instead...
edit
useState is a hook, therefore you should be getting this warning:
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.
It's exactly what's a problem here: you use a hook NOT inside the body of a react functional component, you use it in an ordinary js function.
I'm trying to use responsive javascript media queries using useMediaQuery however I can't get it to work, I get: -
Error message:
"useState" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function
Playground
https://stackblitz.com/edit/react-ts-5vseqr?file=media-query.ts
I think it's erroring on line 4 of media-query.ts
import { useState, useEffect } from 'react'
const useMediaQuery = (query: string) => {
const [match, setMatch] = useState(false)
useEffect(() => {
const updateMatch = () => setMatch(window.matchMedia(query).matches)
updateMatch()
window.matchMedia(query).addEventListener('change', updateMatch)
return () => {
window.matchMedia(query).removeEventListener('change', updateMatch)
}
}, [query])
return match
}
export default useMediaQuery
What you've done here is writing a custom hook(useMediaQuery). You've done that properly so no issues there. Above code snipped is fine.
The problem is in the index.tsx file when you try to use the above custom hook that you've written. As the error suggests your custom hook is called outside the react component there in line 7 of index.tsx.
You have to move the useMediaQuery call inside the App component. Also currently your App component is a class component which you have to convert to a functional component to use hooks inside it.
here's the adjusted code:
https://stackblitz.com/edit/react-ts-m6rwpd?file=index.tsx