ค้นหาเว็บไซต์

reactjs - ข้อผิดพลาด: คุณสมบัติ 'title' ไม่มีอยู่ในประเภท 'never' แต่ฉันเห็นบันทึกในเบราว์เซอร์


ฉันได้รับข้อผิดพลาด:

คุณสมบัติ 'title' ไม่มีอยู่ในประเภท 'never'. ..... console.log(blog.title);

แต่ที่คอนโซลของเบราว์เซอร์ฉันสามารถเห็น "blog.title"

นี่คือภาพหน้าจอจากเบราว์เซอร์

ในไฟล์นี้ฉันใช้ console.log และได้รับข้อผิดพลาด:

const BlogDetails = () => {
  const { id } = useParams<{ id: string }>();
  const {
    data: blog,
    error,
    isPending,
  } = useFetch("http://localhost:8500/blogs/" + id);

  console.log(blog&& blog.title);
  

  return (
    <div className="blog-details">
      {isPending && <div>loading...</div>}
      {error && <div>{error}</div>}
      {blog && (
        <article>
          <h2>BlogDetails</h2>
        </article>
      )}
    </div>
  );
};

export default BlogDetails;

ฉันใช้ฮุคที่กำหนดเองเพื่อดึงข้อมูล:

import { useState, useEffect } from "react";
    
    const useFetch = (url: string) => {
      const [data, setData] = useState(null);
      const [isPending, setIsPending] = useState(true);
      const [error, setError] = useState(null);
    
      useEffect(() => {
        const abortCont = new AbortController();
    
        setTimeout(() => {
          fetch(url, { signal: abortCont.signal })
            .then((res) => {
              if (!res.ok) {
                throw Error("could not fetch the data for that resource");
              }
              return res.json();
            })
            .then((data) => {
              setIsPending(false);
              setData(data);
              setError(null);
            })
            .catch((err) => {
              if (err.name === "AbortError") {
                console.log("fetch aborted");
              } else {
                setIsPending(false);
                setError(err.message);
              }
            });
        }, 1000);
        return () => abortCont.abort();
      }, [url]);
      return { data, isPending, error };
    };
    
    export default useFetch;

คำตอบ #1

Typescript ไม่สามารถอนุมานชนิดข้อมูลจากการเรียก API ได้ ดังนั้นคุณจะต้องระบุชนิดข้อมูลเหล่านั้นอย่างชัดเจน

อย่างไรก็ตาม เนื่องจาก useFetch เป็นฟังก์ชันแบบทั่วไป คุณจะต้องเพิ่มประเภทที่เหมาะสมกับการเรียกใช้งาน และส่งมันไปยัง useState ภายใน นอกจากนี้ ค่าตั้งต้นของ useState คือ null ดังนั้นเราควรพิจารณาสิ่งนั้นด้วย

เราสามารถเพิ่มชนิดทั่วไปเพื่อ useFetch - <T> และพิมพ์ useState<T | null>() เพื่ออนุญาตประเภทข้อมูลที่ต้องการ และ null:

export const useFetch = <T>(url: string) => {
  const [data, setData] = useState<T | null>(null);

ในการใช้งาน คุณจะต้องส่งประเภทที่ชัดเจนไปยัง useFetch ตัวอย่างเช่น:

interface Data { 
  title: string;
  body: string;
  author: string;
  id: number;
}

const { data: blog, error, isPending } = useFetch<Data>(
  'http://localhost:8500/blogs/' + id
);

console.log(blog && blog.title); // or just console.log(blog?.title) with optional chaining

ทุกครั้งที่คุณเรียก useFetch คุณควรระบุประเภทข้อมูลที่เหมาะกับการตอบสนองปัจจุบัน ตัวอย่างเช่น:

useFetch<string[]>( // the result is an array of strings

useFetch<Data[]>( // the result is an array of data objects

useFetch<number>( // the result is a number