reactjs - Tipo no es asignable al tipo 'never' (Next.js, TypeScript) error en la compilación
Tengo este error en la consola al intentar construir mi proyecto:
.next/types/app/facebook/page.ts:8:13
Type error: Type 'OmitWithTag<typeof import("D:/projects/abkh24/client/app/facebook/page"), "metadata" | "default" | "config" | "generateStaticParams" | "revalidate" | "dynamic" | "dynamicParams" | "fetchCache" | "preferredRegion" | "runtime" | "maxDuration" | "generateMetadata", "">' does not satisfy the constraint '{ [x: string]: never; }'.
Property 'fetchUser' is incompatible with index signature.
Type '(id: string, token: string) => Promise<UserData | null>' is not assignable to type 'never'.
6 |
7 | // Check that the entry is a valid entry
> 8 | checkFields<Diff<{
| ^
9 | default: Function
10 | config?: {}
11 | generateStaticParams?: Function
error Command failed with exit code 1.
Este es el componente con la función fetchUser que hace una solicitud a Facebook Graph API para obtener el avatar de un usuario y otros datos. Intenté escribirlo con tipos, pero ocurre un error. El código del componente está a continuación:
"use client";
import { Box } from "@mui/material";
import React, { useState, useEffect, Fragment } from "react";
import Spinner from "@/components/Spinner";
import { useIsMount } from "@/misc/tools";
import { useAppDispatch, useAppSelector } from "@/store/hooks";
import { setAuth } from "@/store/authSlice";
import { RootState } from "@/store";
import { redirect } from "next/navigation";
const ACCESS_TOKEN = process.env.NEXT_PUBLIC_ACCESS_TOKEN;
type UserData = {
avatar: string;
category: string;
name: string;
};
function stringBetweenStrings(
startStr: string,
endStr: string,
str: string,
): string {
const pos = str.indexOf(startStr) + startStr.length;
return str.substring(pos, str.indexOf(endStr, pos));
}
export const fetchUser = async (
id: string,
token: string,
): Promise<UserData | null> => {
try {
const response = await fetch(
`https://graph.facebook.com/${id}?fields=name,picture&access_token=${token}`,
);
const data = await response.json();
return {
avatar: data.picture.data.url,
category: "facebook",
name: data.name,
};
} catch (error) {
console.error("Error fetching user data", error);
return null;
}
};
export default function page() {
const { name, avatar, category } = useAppSelector(
(state: RootState) => state.auth,
);
const dispatch = useAppDispatch();
const isMount = useIsMount();
const [facebookId, setFacebookId] = useState<string>('');
useEffect(() => {
const myUrl = window.location.href;
setFacebookId(stringBetweenStrings("id=", "#_=_", myUrl));
}, []);
useEffect(() => {
(async () => {
if (!isMount && ACCESS_TOKEN) {
const data: UserData | null = await fetchUser(facebookId, ACCESS_TOKEN);
dispatch(setAuth({ ...data, id: facebookId }));
}
})();
}, [facebookId]);
useEffect(() => {
if (!isMount && category) {
redirect("/");
}
}, [category]);
return (
<Fragment>
<Box
sx={{
position: "fixed",
zIndex: 111,
top: 0,
left: 0,
height: "100vh",
width: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
background: "#fff",
}}
></Box>
<Spinner />
</Fragment>
);
}
El proyecto está basado en Next.js 13, utiliza Eslint y otras herramientas. Gracias por su atención.
Respuesta #1
Este código funciona, pero usa passport.js con callbacks. En este momento prefiero Firebase.
"use client";
import { Box } from "@mui/material";
import React, { useState, useEffect, Fragment } from "react";
import Spinner from "@/components/Spinner";
import { useIsMount } from "@/misc/tools";
import { useRouter } from "next/navigation";
import { ReduxState, useAppDispatch, useAppSelector } from "@/lib";
import { setAuth } from "@/lib/authSlice";
import { setField } from "@/lib/formSlice";
const ACCESS_TOKEN = process.env.NEXT_PUBLIC_ACCESS_TOKEN;
function stringBetweenStrings(
startStr: string,
endStr: string,
str: string,
): string {
const pos = str.indexOf(startStr) + startStr.length;
return str.substring(pos, str.indexOf(endStr, pos));
}
export default function Facebook() {
const router = useRouter();
const { name, avatar, category } = useAppSelector(
(state: ReduxState) => state.auth,
);
const dispatch = useAppDispatch();
const isMount = useIsMount();
const [facebookId, setFacebookId] = useState<string | null>(null);
useEffect(() => {
const myUrl = window.location.href;
setFacebookId(stringBetweenStrings("id=", "#_=_", myUrl));
}, []);
useEffect(() => {
if (!isMount && facebookId) {
(async () => {
const response = await fetch(
`https://graph.facebook.com/${facebookId}?fields=name,picture&access_token=${ACCESS_TOKEN}`,
);
const data = await response.json();
await dispatch(
setAuth({
avatar: data.picture.data.url,
category: "facebook",
name: data.name,
id: facebookId,
}),
);
await dispatch(
setField({ field: "root", value: `userid${facebookId}` }),
);
})();
}
}, [facebookId]);
useEffect(() => {
if (!isMount && category) {
router.push("/");
}
}, [category]);
return (
<Fragment>
<Box
sx={{
position: "fixed",
zIndex: 111,
top: 0,
left: 0,
height: "100vh",
width: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
background: "#fff",
}}
></Box>
<Spinner />
</Fragment>
);
}
Respuesta #2
¿Podrías intentar revisar el export de tu página?
Incorrecto: export {[nombre-de-la-página]} - exportación de nombre
Debería ser: export default [nombre-de-la-página] - exportación por defecto
