我当前正尝试用对graphql端点的调用来替换我的宁静调用,以从服务器检索我的所有articles
。我已经用GraphiQL
测试了以下查询,它返回了预期的数据。我还使用fiddler手动将其发布到了端点,并且它按预期运行。我的问题是尝试使用Apollo
从react组件调用终结点。
我当前收到以下错误:
TypeError: parse is not a function
我的graphql查询返回的数据示例:
{
"data": {
"articles": [
{
"id": 1,
"description": "desc1"
},
{
"id": 2,
"description": "desc2"
}
]
}
}
和完整的组件:
import React, { Component } from 'react';
import { Glyphicon } from 'react-bootstrap';
import { LinkContainer } from 'react-router-bootstrap';
import { Query } from "react-apollo";
import gql from "graphql-tag";
export class ArticlesIndex extends Component {
displayName = ArticlesIndex.name
constructor(props) {
super(props);
this.state = { articles: [], loading: true };
}
componentDidMount () {
<Query
query={gql`
query GetArticleData {
articles {
id
description
}
}
`}
>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
console.log(data.articles);
this.setState({articles: data.articles, loading: false});
}}
</Query>
}
renderArticlesTable = articles => {
return (
<table className='table'>
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Description</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{articles.map(article =>
<tr key={article.id}>
<td>{article.id}</td>
<td>{article.title}</td>
<td dangerouslySetInnerHTML={{ __html: article.description }}></td>
<td>
<LinkContainer to={'/articles/edit/' + article.id}>
<Glyphicon glyph='edit' />
</LinkContainer>
</td>
<td onClick={(e) => this.deleteArticle(e, article.id) }>
<Glyphicon glyph='trash' />
</td>
</tr>
)}
</tbody>
</table>
);
}
render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: this.renderArticlesTable(this.state.articles);
return (
<div>
<h1>Articles</h1>
<LinkContainer to={'/articles/create'}>
<button type="button" className="btn btn-default">New Article</button>
</LinkContainer>
{contents}
</div>
);
}
deleteArticle(event, id) {
fetch('https://localhost:44360/api/articles/' + id, {
method: 'DELETE'
}).then((response) => response.json())
.then((responseJson) => {
var deletedId = responseJson.id;
this.setState({
articles: this.state.articles.filter(function( obj ) {
return obj.id !== deletedId;
})
});
})
}
}
请注意,我的断点未在服务器端命中,并且未对服务器发出任何请求。
在App.js
中,我按如下所示设置了ApolloClient
和ApolloProvider
:
client = new ApolloClient({
uri: "https://localhost:44360/graphql"
});
render() {
return (
<ApolloProvider client={this.client}>
<Layout>
<Route exact path='/' component={Home} exact={true} />
<Route path='/articles' component={ArticlesIndex} exact={true} />
<Route path='/articles/create' component={ArticlesCreate} exact={true} />
<Route path='/articles/edit/:id' component={ArticlesEdit} exact={true} />
</Layout>
</ApolloProvider>
);
}
为什么会这样,我该如何克服呢?
编辑:正如我在其他地方看到的建议,我将graphql
npm软件包降级为版本0.12.3
,这在控制台或其他方面均未导致任何错误,但屏幕停留在Loading...
仍然没有任何请求发送到服务器。
编辑2:我现在尝试了列出的所有here解决方法,并在尝试更改webpack配置的建议后,页面不会像以前一样出错,但是仍然没有请求发送到服务器,并且{ {1}}永远停留在页面上。我的Loading...
函数中的断点被击中,但似乎什么也没发生。
编辑3:如果我用下面的静态调用替换了graphql调用以获取数据,则一切正常,但是该项目的目的是探索对graphql的反应。正常运行且我要替换的宁静呼叫如下:
componentDidMount
答案 0 :(得分:2)
您在componentDidMount
中使用了JSX,相反,您可以执行this.props.client.query({query: GET_ARTICLES})
,我对其进行了测试,它可以正常工作。
将您的articles/index.js
更改为
import React, { Component } from "react";
import { Glyphicon } from "react-bootstrap";
import { LinkContainer } from "react-router-bootstrap";
import { Query, withApollo } from "react-apollo";
import gql from "graphql-tag";
const GET_ARTICLES = gql`
query GetArticleData {
articles {
id
description
}
}
`;
class ArticlesIndex extends Component {
state = { articles: [], loading: true };
displayName = ArticlesIndex.name;
componentDidMount = () => {
const { client } = this.props;
client
.query({ query: GET_ARTICLES })
.then(({ data: { articles } }) => {
if (articles) {
this.setState({ loading: false, articles });
}
})
.catch(err => {
console.log("err", err);
});
};
renderArticlesTable = articles => {
return (
<table className="table">
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Description</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{articles.map(article => (
<tr key={article.id}>
<td>{article.id}</td>
<td>{article.title}</td>
<td dangerouslySetInnerHTML={{ __html: article.description }} />
<td>
<LinkContainer to={"/articles/edit/" + article.id}>
<Glyphicon glyph="edit" />
</LinkContainer>
</td>
<td onClick={e => this.deleteArticle(e, article.id)}>
<Glyphicon glyph="trash" />
</td>
</tr>
))}
</tbody>
</table>
);
};
render() {
let contents = this.state.loading ? (
<p>
<em>Loading...</em>
</p>
) : (
this.renderArticlesTable(this.state.articles)
);
return (
<div>
<h1>Articles</h1>
<LinkContainer to={"/articles/create"}>
<button type="button" className="btn btn-default">
New Article
</button>
</LinkContainer>
{contents}
</div>
);
}
deleteArticle(event, id) {
fetch("https://localhost:44360/api/articles/" + id, {
method: "DELETE"
})
.then(response => response.json())
.then(responseJson => {
var deletedId = responseJson.id;
this.setState({
articles: this.state.articles.filter(function(obj) {
return obj.id !== deletedId;
})
});
});
}
}
export default withApollo(ArticlesIndex);
将您的App.js
更改为
import React, { Component } from "react";
import { Route } from "react-router";
import { Layout } from "./components/Layout";
import { Home } from "./components/Home";
import ArticlesIndex from "./components/articles/Index";
import { ArticlesCreate } from "./components/articles/Create";
import { ArticlesEdit } from "./components/articles/Edit";
import { ApolloProvider } from "react-apollo";
import ApolloClient from "apollo-boost";
export default class App extends Component {
displayName = App.name;
client = new ApolloClient({
uri: "https://localhost:44360/graphql"
});
render() {
return (
<ApolloProvider client={this.client}>
<Layout>
<Route exact path="/" component={Home} exact={true} />
<Route path="/articles" component={ArticlesIndex} exact={true} />
<Route
path="/articles/create"
component={ArticlesCreate}
exact={true}
/>
<Route
path="/articles/edit/:id"
component={ArticlesEdit}
exact={true}
/>
</Layout>
</ApolloProvider>
);
}
}
问题是您在ComponentDidMount
内使用了JSX,这在react中不受支持,为了在生命周期方法中使用查询,您应该使用withApollo
包装该组件,将客户添加到道具(因此export default withApollo(ArticlesIndex);
)中,然后可以在this.props.client.query
中进行componentDidMount
,然后可以设置状态。