react js - Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

时间:2021-03-08 20:58:32

标签: javascript node.js reactjs react-native frontend

我对反应还很陌生,我正在开发一个组件,该组件将从本地 JSON 文件中获取数据并将其输出到表组件。

我目前卡在加载屏幕上,出现以下错误,未捕获(承诺)SyntaxError: Unexpected token < in JSON at position 0

我的第一个想法是 JSON 文件可能已损坏,我已经使用 JSON lint 测试了 JSON 文件并且它是有效的。

App.js

import React, { useEffect, useState, useMemo } from "react";
import './App.css';

import Search from './components/Search'
import TableHeader from './components/Header'
import Pagination from './components/Pagination'

import useFullPageLoader from "./hooks/useFullPageLoader";

import mockData from './MOCK_DATA.json';

function App() {
  const [details, setDetails] = useState([]);
  const [loader, showLoader, hideLoader] = useFullPageLoader();
  const [totalItems, setTotalItems] = useState(0);
  const [currentPage, setCurrentPage] = useState(1);
  const [search, setSearch] = useState("");
  const [sorting, setSorting] = useState({ field: "", order: "" });

  const ITEMS_PER_PAGE = 50;

  const headers = [
      { name: "id", field: "id", sortable: false },
      { name: "first_name", field: "first_name", sortable: true },
      { name: "last_name", field: "last_name", sortable: true },
      { name: "email", field: "email", sortable: false },
      { name: "gender", field: "gender", sortable: false },
      { name: "ip_address", field: "ip_address", sortable: false }
  ];

  useEffect(() => {
    const getData = () => {
      showLoader();

      fetch(mockData)
          .then(response => response.json())
          .then(json => {
            hideLoader();
            setDetails(json);
        });
    };

      getData();
    }, []);

  const detailsData = useMemo(() => {
      let computedDetails = details;

      if (search) {
          computedDetails = computedDetails.filter(
              detail =>
                  detail.first_name.toLowerCase().includes(search.toLowerCase()) ||
                  detail.last_name.toLowerCase().includes(search.toLowerCase())
          );
      }

      setTotalItems(computedDetails.length);

      //Sorting comments
      if (sorting.field) {
          const reversed = sorting.order === "asc" ? 1 : -1;
          computedDetails = computedDetails.sort(
              (a, b) =>
                  reversed * a[sorting.field].localeCompare(b[sorting.field])
          );
      }

      //Current Page slice
      return computedDetails.slice(
          (currentPage - 1) * ITEMS_PER_PAGE,
          (currentPage - 1) * ITEMS_PER_PAGE + ITEMS_PER_PAGE
      );
  }, [details, currentPage, search, sorting]);

  return (
    <div className="row w-100">
      <div className="col mb-3 col-12 text-center">
        <div className="row">
          <div className="col-md-6">
            <Pagination
                total={totalItems}
                itemsPerPage={ITEMS_PER_PAGE}
                currentPage={currentPage}
                onPageChange={page => setCurrentPage(page)}
            />
          </div>
          <div className="col-md-6 d-flex flex-row-reverse">
            <Search
                onSearch={value => {
                    setSearch(value);
                    setCurrentPage(1);
                }}
            />
          </div>
        </div>

        <table className="table table-striped">
          <TableHeader
              headers={headers}
              onSorting={(field, order) =>
                  setSorting({ field, order })
              }
          />
          <tbody>
              {detailsData.map(detail => (
                  <tr>
                      <th scope="row" key={detail.id}>
                          {detail.id}
                      </th>
                      <td>{detail.first_name}</td>
                      <td>{detail.last_name}</td>
                      <td>{detail.email}</td>
                      <td>{detail.gender}</td>
                      <td>{detail.ip_address}</td>
                  </tr>
              ))}
          </tbody>
        </table>
      </div>
      {loader}
    </div>
  );
};

export default App;

MOCK_DATA.json

[{"id":1,"first_name":"Felicdad","last_name":"McKimmie","email":"fmckimmie0@lycos.com","gender":"Agender","ip_address":"99.216.194.167"},
{"id":2,"first_name":"Reinald","last_name":"Capelen","email":"rcapelen1@e-recht24.de","gender":"Male","ip_address":"193.151.24.49"},
{"id":3,"first_name":"Francyne","last_name":"Sheers","email":"fsheers2@surveymonkey.com","gender":"Genderqueer","ip_address":"117.134.38.199"},
{"id":4,"first_name":"Luelle","last_name":"Reynold","email":"lreynold3@tumblr.com","gender":"Polygender","ip_address":"203.34.23.135"},
{"id":5,"first_name":"Ivy","last_name":"Perrottet","email":"iperrottet4@elpais.com","gender":"Bigender","ip_address":"106.12.116.189"},
{"id":6,"first_name":"Tobye","last_name":"Petyt","email":"tpetyt5@bbb.org","gender":"Polygender","ip_address":"225.146.16.182"},
{"id":7,"first_name":"Eliot","last_name":"Maginn","email":"emaginn6@state.tx.us","gender":"Bigender","ip_address":"193.19.188.237"},
{"id":8,"first_name":"Ciel","last_name":"Lucio","email":"clucio7@lulu.com","gender":"Polygender","ip_address":"249.65.61.1"},
{"id":9,"first_name":"Haslett","last_name":"Farris","email":"hfarris8@noaa.gov","gender":"Male","ip_address":"247.37.86.113"},
{"id":10,"first_name":"Sunshine","last_name":"Gascard","email":"sgascard9@netvibes.com","gender":"Non-binary","ip_address":"118.125.194.37"},
{"id":11,"first_name":"Dieter","last_name":"Marner","email":"dmarnera@springer.com","gender":"Female","ip_address":"212.250.147.88"},
{"id":12,"first_name":"Oliy","last_name":"Manicomb","email":"omanicombb@arizona.edu","gender":"Agender","ip_address":"166.17.214.135"},
{"id":13,"first_name":"Jacky","last_name":"Beidebeke","email":"jbeidebekec@wunderground.com","gender":"Female","ip_address":"75.17.95.9"},
{"id":14,"first_name":"Berton","last_name":"Juan","email":"bjuand@bandcamp.com","gender":"Bigender","ip_address":"254.215.187.1"},
{"id":15,"first_name":"Gerick","last_name":"Freezor","email":"gfreezore@vkontakte.ru","gender":"Agender","ip_address":"140.42.52.239"},
{"id":16,"first_name":"Adore","last_name":"Millichip","email":"amillichipf@php.net","gender":"Genderfluid","ip_address":"67.110.77.105"},
{"id":17,"first_name":"Clim","last_name":"Gribbon","email":"cgribbong@google.de","gender":"Female","ip_address":"109.101.93.221"},
{"id":18,"first_name":"Ozzy","last_name":"Harbert","email":"oharberth@yelp.com","gender":"Male","ip_address":"217.37.94.242"},
{"id":19,"first_name":"Zonnya","last_name":"Connock","email":"zconnocki@webnode.com","gender":"Genderfluid","ip_address":"112.216.14.43"},
{"id":20,"first_name":"Quincy","last_name":"Dorton","email":"qdortonj@jugem.jp","gender":"Genderqueer","ip_address":"112.2.53.222"}]

1 个答案:

答案 0 :(得分:2)

fetch 需要一个 URL,以便从某个端点获取数据。

你给了它一个 JSON,它不知道如何处理它。如果您想使用虚假数据,您可以在 useEffect

const getData = () => {
    showLoader();

    Promise.resolve(mockData)
        .then(json => {
          hideLoader();
          setDetails(json);
      });
  };