Búsqueda de sitios web

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