代码之家  ›  专栏  ›  技术社区  ›  GregH

与graphql反应:typeerror:parse不是函数

  •  0
  • GregH  · 技术社区  · 5 年前

    我正在尝试替换我的restful调用以检索所有 articles 从服务器调用graphql端点。我已经用 GraphiQL 它返回预期的数据。我还使用fiddler手动发布到端点,它按预期运行。我的问题是试图使用 Apollo .

    我当前收到以下错误:

    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配置的建议之后,页面不会像以前那样出错,但是仍然没有请求发送到服务器,并且 加载。。。 永远留在页面上。我的断点 componentDidMount 函数正在被击中,但似乎什么也没有发生。

    编辑3:如果我用下面的restful调用替换graphql调用以获取数据,那么一切都会正常运行,但是这个项目的目的是探索graphql的反应。下面是restful调用,它运行正常,我正在尝试替换它:

    fetch('https://localhost:44360/api/Articles/')
          .then(response => response.json())
          .then(data => {
            this.setState({ articles: data, loading: false });
          });
    
    0 回复  |  直到 5 年前
        1
  •  2
  •   Rachid Rhafour    5 年前

    你用了jsx componentDidMount ,相反,你可以 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 ,这在react中不受支持,为了在生命周期方法中使用query,应该用 withApollo 这将把客户端添加到道具中(因此 export default withApollo(ArticlesIndex); ),那你就可以 this.props.client.query 在里面 组件 然后你可以设置状态。