如何使用 Apollo Graphql 客户端和 React 解决“TypeError:无法读取未定义的属性“参数”?
Posted
技术标签:
【中文标题】如何使用 Apollo Graphql 客户端和 React 解决“TypeError:无法读取未定义的属性“参数”?【英文标题】:How to solve 'TypeError: Cannot read property 'params' of undefined' with Apollo Graphql Client and React? 【发布时间】:2019-05-28 19:54:06 【问题描述】:我正在尝试连接一个套牌 URL 以链接到卡片列表,类似于我在 Traversy's SpaceX graphql demo 上看到的那样。单击任一演示卡组的链接时,我收到错误 TypeError: Cannot read property 'params' of undefined。
这是我在服务器之上构建的 React 客户端,使用 Apollo 和 GraphQL 连接到我的功能性 PostgreSQL 数据库。我已经将问题定位为这些行,以及道具是如何通过 React 和 Apollo 传递的。请注意,我是 GraphQL 和 Apollo 的初学者,这是我第一个使用 React 的真正项目,所以任何理解该过程的指导将不胜感激。
let id = this.props.match.params;
id = parseInt(id);
甲板索引.js
import React, Component, Fragment from "react";
import gql from "graphql-tag";
import Query from "react-apollo";
import Loading from "../../Loading";
import DeckItem from "./DeckItem";
const GET_DECKS = gql`
query DeckQuery
decks @connection(key: "DeckConnection")
edges
id
deckName
createdAt
cards
id
front
`;
class Decks extends Component
render()
return (
<Fragment>
<h1>Deck</h1>
<Query query=GET_DECKS>
( data, error, loading ) =>
if (loading)
return <Loading />;
if (error)
return <p>Error</p>;
const decksToRender = data.decks.edges;
return (
<Fragment>
console.log(data)
decksToRender.map(deck => (
<DeckItem key=deck.id deck=deck />
))
</Fragment>
);
</Query>
</Fragment>
);
export default Decks;
DeckItem index.js
import React from "react";
import Moment from "react-moment";
import Link from "react-router-dom";
export default function DeckItem( deck: id, deckName, createdAt )
return (
<div>
<div>
<h2>
<Link to=`/deck/$id`>deckName</Link>
</h2>
<p>Description coming soon...</p>
<h5>
Created on <Moment format="YYYY-MM-DD HH:mm">createdAt</Moment>
</h5>
</div>
</div>
);
卡片 index.js
import React, Component, Fragment from "react";
import gql from "graphql-tag";
import Query from "react-apollo";
import Link from "react-router-dom";
import Loading from "../../../Loading";
const CARDS_QUERY = gql`
query CardsQuery($id: ID!)
deck(id: $id)
id
deckName
cards
id
front
back
`;
export class Cards extends Component
render()
let id = this.props.match.params;
id = parseInt(id);
return (
<Fragment>
<Query query=CARDS_QUERY variables= id >
( data, error, loading ) =>
if (loading)
return <Loading />;
if (error)
return <p>Error</p>;
const
id,
card: front, back
= data.deck;
return (
<div>
<ul>
<h1>
<li>
<span>Id:</span> id
</li>
</h1>
<h4>Details</h4>
<li>Front: front</li>
<li>Back: back</li>
</ul>
<hr />
<Link to="/">Back</Link>
</div>
);
</Query>
</Fragment>
);
export default Cards;
相关的 React 路由路由
```
import Router, Route from "react-router-dom";
```
import FlashCardPage from "../FlashCards";
import Cards from "../FlashCards/Cards/CardsItem";
import * as routes from "../../constants/routes";
<Router>
```
<Route
exact
path=routes.FLASHCARDS
component=() => <FlashCardPage />
/>
<Route exact path=routes.CARDS component=() => <Cards /> />
</div>
</Router>
我的路由文件中的路径是“/deck/:id”
控制台错误日志
react-dom.development.js:19782 Uncaught TypeError: Cannot read property 'params' of undefined
at Cards.render (index.js:23)
index.js:1452 The above error occurred in the <Cards> component:
in Cards (at App/index.js:42)
in component (created by Route)
in Route (at App/index.js:42)
in div (at App/index.js:19)
in Router (at App/index.js:18)
in App (at withSession.js:8)
in Query (at withSession.js:6)
in Unknown (at src/index.js:84)
in ApolloProvider (at src/index.js:83)
结果应该是一个显示卡片列表的套牌,“/deck/1”应该显示来自我的 PostgreSQL 服务器的 2 或 3 张卡片。目前我只能看到带有 url 的卡片组,但是点击后,它会立即抛出错误。其他 Graphql 函数工作正常,并且使用 Playground 查询工作得很好,所以看来我没有正确传递道具。需要任何其他信息,我很乐意提供。谢谢!
【问题讨论】:
【参考方案1】:来自react-router-dom
的Route
组件使用render-prop 模式来扩展它所呈现的组件,提供props
。 [1]
它将这些 props
(match
、location
、history
和 staticContext
)转发到 React.Component
,它在渲染时传递给它的 component
属性。 [2]
在您定义的路由中,它不会传递给 FlashCardPage
或 Cards
组件,因为有无状态函数组件包装它们。
<Route exact path=routes.CARDS component=() => <Cards /> />
这个无状态的函数组件被传递了这些props;您可以负责将这些props
转发到FlashCardPage
和Cards
组件。
<Route exact path=routes.CARDS component=(props) => <Cards ...props /> />
但是,我建议去掉封装Route
中呈现的组件的无状态组件,因为它是多余的。
<Route exact path=routes.CARDS component=Cards />
【讨论】:
谢谢,您的指示非常有效,帮助我理解了为什么我无法让它工作!您关于摆脱无状态组件的建议我当然也会遵循。以上是关于如何使用 Apollo Graphql 客户端和 React 解决“TypeError:无法读取未定义的属性“参数”?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 React-Apollo 处理 GraphQL 错误?
GraphQL:Apollo 客户端缓存如何工作以保持与服务器的数据一致性?
在客户端解析器中导入类型时,如何避免使用 Apollo 客户端和“graphql-codegen”的角度项目中的循环依赖?
如何使用 apollo 客户端在 graphql 的角度处理错误?