当前位置: 首页 > 知识库问答 >
问题:

未捕获(在promise中)类型错误:无法读取未定义的属性“字段”(React+Contentful)

颜高朗
2023-03-14

我试图创建一个“投资组合”网站来学习反应。我已经从Contentul插入了内容,但是我得到了一个错误:uncatted(在promise中)typeError:当试图显示我的内容时,不能读取未定义的的属性“fields”。

    null
## contentful.js

const client = require('contentful').createClient({
  space: 'MYSPACEID',
  accessToken: 'MYACCESSTOKEN',
});

const getProjectItems = () => client.getEntries().then((response) => response.items);

const getSingleProject = (slug) =>
  client
    .getEntries({
      'fields.slug': slug,
      content_type: 'project',
    })
    .then((response) => response.items);

export { getProjectItems, getSingleProject };

然后,我创建了2个自定义钩子来获取我的内容:

## UseProjects.js

import { useEffect, useState } from 'react';

import { getProjectItems } from '../contentful';

const promise = getProjectItems();

export default function useProjects() {
  const [projects, setProjects] = useState([]);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {
    promise.then((project) => {
      setProjects(project);
      setLoading(false);
    });
  }, []);

  return [projects, isLoading];
}
## useSingleProject.js

import { useEffect, useState } from 'react';

import { getSingleProject } from '../contentful';

export default function useSingleProject(slug) {
  const promise = getSingleProject(slug);

  const [project, setProject] = useState(null);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {
    promise.then((result) => {
      setProject(result[0].fields);
      setLoading(false);
    });
  }, [promise]);

  return [project, isLoading];
}

我可以添加我的组件代码,如果需要,但我觉得我的错误来自这里…奇怪的是,如果我关闭错误,我会看到所有的项目都被正确地呈现(所以...它们被正确地从满足中拉出来),如果我点击它,我会得到正确的信息显示(标题,图像,等等)。但是这个错误会产生奇怪的布局问题。

错误来自我的usesingleProject.js文件(usesingleProject.js:13)

## App.js

import React, { useEffect } from 'react';
import { Route } from 'react-router-dom';
import { gsap } from 'gsap';
import './styles/App.scss';
import Header from './components/header';
import Navigation from './components/navigation';

import CaseStudies from './pages/caseStudies';
import Approach from './pages/approach';
import Services from './pages/services';
import About from './pages/about';
import Home from './pages/home';
import Projects from './pages/projects';
import SingleProject from './pages/SingleProject';

const routes = [
  { path: '/', name: 'Home', Component: Home },
  { path: '/case-studies', name: 'caseStudies', Component: CaseStudies },
  { path: '/approach', name: 'approach', Component: Approach },
  { path: '/services', name: 'services', Component: Services },
  { path: '/about-us', name: 'about', Component: About },
  { path: '/projects', name: 'projects', Component: Projects },
  { path: '/:id', name: ':id', Component: SingleProject },
];

function debounce(fn, ms) {
  let timer;
  return () => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      timer = null;
      fn.apply(this, arguments);
    }, ms);
  };
}

function App() {
  const [dimensions, setDimensions] = React.useState({
    height: window.innerHeight,
    width: window.innerWidth,
  });

  useEffect(() => {
    // prevents flashing
    gsap.to('body', 0, { css: { visibility: 'visible' } });
    const debouncedHandleResize = debounce(function handleResize() {
      setDimensions({
        height: window.innerHeight,
        width: window.innerWidth,
      });
    }, 1000);

    window.addEventListener('resize', debouncedHandleResize);
    return () => {
      window.removeEventListener('resize', debouncedHandleResize);
    };
  });
  return (
    <>
      <Header dimensions={dimensions} />
      <div className="App">
        {routes.map(({ path, Component }) => (
          <Route key={path} exact path={path}>
            <Component dimensions={dimensions} />
          </Route>
        ))}
      </div>
      <Navigation />
    </>
  );
}

export default App;

共有1个答案

穆宾白
2023-03-14

您的钩子useSingleProject的编码方式可以触发无限重呈现循环。下面是我所描述的行为的复制品:https://codesandbox.io/s/bustomed-banach-tr609?file=/src/index.js。观察控制台如何永远记录。

发生这种情况是因为钩子useSingleProject将在每次重新呈现时被调用,每次都会创建一个新的promise。反过来,当promise被更改时,useEffect将触发,导致最终的状态更新,这也意味着最终的重新呈现。这会导致无限循环。

解决方案是使您的效果依赖于slug而不是promise。事实上,您甚至不需要先将promise赋值给变量。

另外,以防万一,只有在实际必须获取数据时,才将isloading设置为true才有意义。所以:

export default function useSingleProject(slug) {
  const [project, setProject] = useState(null);
  const [isLoading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true)

    getSingleProject(slug).then((result) => {
      setProject(result[0].fields);
      setLoading(false);
    });
  }, [slug]);

  return [project, isLoading];
}
 类似资料:
  • 我想有一个无限滚动的项目列表,我正在使用这个包https://github.com/CassetteRocks/react-infinite-scroller但是在留档中没有提到抓取功能的样子。 在我的代码中,它是这样的: 完整消息错误: 未捕获(promise中)类型错误:无法读取评估时未定义的属性“companys”(traineships.component.js:71) 编辑:(我不再有错

  • 我使用的是最新版本的react路由器(版本^3.0.0)。 我使用ES5编写了以下路由: : 在另一个名为

  • 我正在选择area_enninFantry的所有子div,并循环调整某些子div的文本。cardArray是一个全局常量,myId在父函数中定义。 未捕获的TypeError:无法读取未定义的属性(读取“getAttribute”) 我在这篇文章中读到,这可能是因为字段/元素的内容可能是DOM元素,我应该用$()包装它们,所以我确实这样做了——将两个变量都更改为$(元素)[a]. attr(“标题

  • 我遇到了一个有趣的问题,这使我感到困惑。我正在执行一个正确返回数据的Sharepoint RestAPI调用,当我在数据上运行for循环时,它生成html,但仍然抛出我用作标题的错误。代码如下。如果我记录每个循环,它将返回值。HTML也可以很好地工作。问题是错误仍然会出现。

  • 我正在使用一个面向对象的图表,并根据滚动位置设置数据。我使用d3.csv()加载then()的数据,如下所示: 对我来说,包含滚动库以及图表的所有代码是相当复杂的,所以我希望上面足够清楚。我的主要问题是调用在没有()显示图形,但返回标题中的错误。 我正在使用d3.v6,有人能帮忙吗?

  • 我使用react router(我使用的是^4.0.0版本)时遇到了一些问题。 这是我的index.js app.js就是任何东西。我在这里贴的是基本的,因为这不是问题所在(我相信) 这就是当我检查控制台日志时会发生的情况 哦,这是package.json以防万一 我一直在其他地方查这个,但是我没有找到解决的方法。 非常感谢你们的耐心和帮助!!