使用 typescript、react 和 graphql 以正确方式进行查询的问题

Posted

技术标签:

【中文标题】使用 typescript、react 和 graphql 以正确方式进行查询的问题【英文标题】:Problem with make query in correct way using typescript, react and graphql 【发布时间】:2021-01-26 05:18:13 【问题描述】:

请原谅我这个可能很愚蠢的问题,但这是我使用 graphql 并做出反应的第一步。我尝试创建内部是 GraphQL 查询和传入道具的组件。 Props 是一个应该传递给 GraphQL 查询的查询。我知道我做错了什么,但我不知道是什么。我将带有 apollo 提供程序的客户端之类的所有内容添加到我的应用程序组件结构中。 在主页(index.js)上,我的布局很简单:

import Layout from "../components/layout"
import SearchForm from "../components/searchForm"

export default function Home() 
  return  (
    <Layout pageTitle="React App" headerTitle="Search repositories on Github">
      <SearchForm repositoryNameDefaultValue='' />
    </Layout>
  );

然后我有一个名为 searchForm 的组件:

import  Component, ChangeEvent  from "react";
import Input from "./input";
import Button from "./button";
import style from "./searchForm.module.scss";
import FindRepositoryResults from "./test";

interface IMyComponentErrors 
  repositoryNameError: string;


interface IMyComponentProps 
  repositoryNameDefaultValue: string;


interface IMyComponentState 
  repositoryName: string;
  formIsSend: boolean;
  errors: IMyComponentErrors;


const validateForm = (errors: IMyComponentErrors): boolean => 
  let valid = true;
  Object.values(errors).forEach((val) => val.length > 0 && (valid = false));
  return valid;
;

const validRepositoryNameRegex = RegExp(/^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$/i);

export default class SignUpFormContainer extends Component<
  IMyComponentProps,
  IMyComponentState
> 
  constructor(props: IMyComponentProps) 
    super(props);
    this.state = 
      repositoryName: this.props.repositoryNameDefaultValue,
      formIsSend: false,
      errors: 
        repositoryNameError: "",
      
    ;

    this.handleFormSubmit = this.handleFormSubmit.bind(this);
    this.handleClearForm = this.handleClearForm.bind(this);
    this.handleChangeRepositoryName = this.handleChangeRepositoryName.bind(this);
  

  handleChangeRepositoryName(event: ChangeEvent<htmlInputElement>): void 
    event.preventDefault();
    const  value  = event.target;
    let errors = this.state.errors;

    if (!validRepositoryNameRegex.test(value)) 
      errors.repositoryNameError = "Invalid repository name";
     else if (!value) 
      errors.repositoryNameError = "Repository name is required";
     else 
      errors.repositoryNameError = "";
    

    this.setState( errors, repositoryName: value );
  

  handleClearForm() 
    this.setState(
      repositoryName: "",
      formIsSend: false
    );
  

  handleFormSubmit(event) 
    event.preventDefault();
    const  repositoryName  = this.state;
    let errors = this.state.errors;

    if (!repositoryName) 
      errors.repositoryNameError = "Repository name is required";
    

    this.setState( errors );

    if (!validateForm(this.state.errors)) 
      return;
     else 
      this.setState( formIsSend: true );
    
  

  render() 
    const  errors  = this.state;

    return (
      <div>
       !this.state.formIsSend ? (
      <form
        aria-label="Search repositories by name"
        autoComplete="off"
        onSubmit=this.handleFormSubmit
        className = style.formSearchRepository
      >
        <Input
          type="text"
          title="Repository name:"
          name="repositoryName"
          placeholder="Enter name of repository"
          value=this.state.repositoryName
          error=errors.repositoryNameError.length > 0
          errorMessage=errors.repositoryNameError
          onChange=this.handleChangeRepositoryName
          required
        />
        <Button
          onClick=this.handleFormSubmit
          title="Search repository in Github by name"
          children="Search"
        />
      </form>
      ) : <FindRepositoryResults repositoryName=this.state.repositoryName/>
      </div>
    );
  

最后一个更成问题的查询在哪里:

import React from "react";
import  gql, useQuery  from "@apollo/client";

const SEARCH_REPOSITORY = gql`
query findRepositories($query: String!) 
    search(first: 10, query: $query, type: REPOSITORY) 
        nodes 
          ... on Repository 
            name,
            owner 
              login
            
            primaryLanguage 
              name
            ,
            stargazers 
              totalCount
            ,
            stargazerCount,
            languages(first: 20, orderBy: field: SIZE, direction: ASC ) 
              totalCount
              nodes 
                name
              
            ,
            issues 
              totalCount
            
            shortDescriptionHTML,
            updatedAt,
            watchers 
              totalCount
            
          
        
    

`;

interface IFindRepositoryComponentProps 
  repositoryName: string;


interface IFindRepositoryComponentState 
  detailsAreOpen: boolean;


interface RepositoryData 
  data: any;


interface RepositoryVars 
  query: string;


export default class FindRepositoryResults extends React.Component<IFindRepositoryComponentProps, IFindRepositoryComponentState> 
  constructor(props: IFindRepositoryComponentProps) 
    super(props);
    this.state =  detailsAreOpen: false ;

    this.showDetails = this.showDetails.bind(this);
  

  showDetails() 
    this.setState(state => (
      detailsAreOpen: !state.detailsAreOpen
    ));
  

  render() 
    const  loading, data, error  = useQuery<any, RepositoryVars>(
      SEARCH_REPOSITORY ,
       variables:  query: this.props.repositoryName  
    );

    return (
      <section>
        <h3>Results</h3>
        loading ? (
          <p>Loading ...</p>
        ) : error ? (<p>Error error</p>) : (
          <div>
             data.search.nodes.length == 0 ? (<p>No results found.</p>) : data && data.search.nodes.map((repo) => (
              <div>
                <p>Name: repo.name</p>
                <p>Owner: repo.owner.login</p>
                <p>Number of stars (total): repo.stargazerCount</p>
                <p>Primary language: repo.primaryLanguage.name</p>
          
                <button onClick=this.showDetails>this.state.detailsAreOpen ? 'Show less' : 'Show more'</button>
                <div>
                  Details:
                  repo.issues.totalCount
                  repo.languages.totalCount
                  repo.shortDescriptionHTML
                  repo.stargazers.totalCount
                  repo.updatedAt
                  repo.watchers.totalCount
                </div>
              </div>
            ))
          </div>
        )
      </section>
    );
     

在上面的这个组件中,我进行了查询,但没有得到结果。我不确定,但版本不匹配(DOM 渲染),我在与 typescript、react 和 apollo 一起正确执行此操作时遇到问题。如果有人能告诉我正确的方法和例子,我会很高兴。谢谢

【问题讨论】:

【参考方案1】:

我没有使用 typescript,但使用了 React hooks 和 GraphQL。因此,您进行了查询,但没有得到任何结果?如果执行查询,则应该有结果或错误。如果它走得那么远,它可能有助于下载 Apollo-Graphql 插件(也许是谷歌浏览器?)。

例如,我会在 graphi-ql 游乐场中尝试查询。

此外,查询中的变量名查询有点混乱。

最好的,J

【讨论】:

以上是关于使用 typescript、react 和 graphql 以正确方式进行查询的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 TypeScript 反应 Apollo useQuery 钩子

Esri 使用 React 和 Typescript 映射

React 和 TypeScript:避免使用上下文默认值

深入浅出TypeScript- 在React项目中使用TypeScript

绝对导入:React 和 Typescript

如何使用 GraphQL 构建 TypeScript+React 应用