【发布时间】: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 一起正确执行此操作时遇到问题。如果有人能告诉我正确的方法和例子,我会很高兴。谢谢
【问题讨论】:
标签: reactjs typescript next.js apollo react-apollo