基于来自初始查询的数据触发第二个GraphQL查询

问题描述 投票:0回答:1

概述

WrappedApp最初加载时,查询被发送到GraphQL API以获取数据(标签)。

完成后,用户可以通过单击ShortList中的标签将项目添加到WrappedApp中的TagsList中(请参见下面的屏幕截图)。

问题

如何在TagsList中单击标签(即在下面的示例中单击了安全性)以触发第二个名为GQLSIMILARTAGS的GraphQL查询,并将结果呈现在ShortList结果上方,或至少在控制台中.log GQLSIMILARTAGS查询的结果? GQLSIMILARTAGS接受一个变量,该变量将是单击并添加到ShortList的标签。

shortlist

我尝试了什么?

[我尝试修改addFavourite中的WrappedApp函数以使用带有GQLFunc的新GQLSIMILARTAGS查询来调用useQuery(GQLSIMILARTAGS),但这可能不是最佳方法。

这是Apollo GraphQL查询代码。

graphclient.js


import React from "react";
import { gql } from "apollo-boost";
import ApolloClient from "apollo-boost";
import { useQuery } from "@apollo/react-hooks";

const client = new ApolloClient({
  uri: "https://job-stats.herokuapp.com/v1/graphql",
});

const GQLTAGS = gql`
  {
    tag(
      order_by: { tag_related_counts_aggregate: { count: desc } }
      where: { label: { _nin: ["None", "null"] } }
    ) {
      id
      label
      tag_related_counts_aggregate {
        aggregate {
          count
        }
      }
    }
  }
`;

    const GQLSIMILARTAGS = gql`
      query ($search_label: String!){
  tag(where: {tag_related_counts: {search_label: {_eq: $search_label}}}, distinct_on: id) {
     label
    tag_related_counts {
      count
      other_label
      search_label
    }
  }
}
`;

function GQLFunc(props) {
  const { loading, error, data } = useQuery(GQLTAGS);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :(</p>;

  let CallingApp = props.callingApp;
  if (data) return <CallingApp data={data.tag} />;
}

export { client, GQLTAGS, GQLFunc };

这是主要的WrappedApp.js应用。

import React, { Component } from "react";

/* ############################ */
/* ##### Single tag ##### */
/* ############################ */

const Tag = ({ id, info, handleFavourite }) => (
  <li className={info.count} onClick={() => handleFavourite(id)}>
    {info.label} ({info.tag_related_counts_aggregate.aggregate.count})
  </li>
);

const Greeting = () => <h1>Test Tags</h1>;

/* ##################### */
/* ##### Shortlist ##### */
/* ##################### */

const ShortList = ({ favourites, data, deleteFavourite }) => {
  const hasFavourites = favourites.length > 0;
  const favList = favourites.map((fav, i) => {
    return (
      <Tag
        id={i}
        key={i}
        info={data.find((tag) => tag.id === fav)}
        handleFavourite={(id) => deleteFavourite(id)}
      />
    );
  });
  return (
    <div className="favourites">
      <h4>
        {hasFavourites
          ? "Shortlist. Click to remove.."
          : "Click on a tag to shortlist it.."}
      </h4>
      <ul>{favList}</ul>
      {hasFavourites && <hr />}
    </div>
  );
};

/* ########################### */
/* ##### Tag list ##### */
/* ########################### */

const TagsList = ({ data, filter, favourites, addFavourite }) => {
  const input = filter;

  // Gather list of tags
  const tags = data
    // filtering out the tags that...
    .filter((tag, i) => {
      return (
        // ...are already favourited
        favourites.indexOf(tag.id) === -1 &&
        // ...are not matching the current search value
        !tag.label.indexOf(input)
      );
    })
    // ...output a <Name /> component for each name
    .map((tag, i) => {
      // only display tags that match current input string
      return (
        <Tag
          id={tag.id}
          key={i}
          info={tag}
          handleFavourite={(id) => addFavourite(id)}
        />
      );
    });

  /* ##### the component's output ##### */
  return <ul>{tags}</ul>;
};

/* ###################### */
/* ##### Search bar ##### */
/* ###################### */

// need a component class here
// since we are using `refs`
class Search extends Component {
  render() {
    const { filterVal, filterUpdate } = this.props;
    return (
      <form>
        <input
          type="text"
          ref="filterInput"
          placeholder="Type to filter.."
          // binding the input value to state
          value={filterVal}
          onChange={() => {
            filterUpdate(this.refs.filterInput.value);
          }}
        />
      </form>
    );
  }
}

/* ############################## */
/* ##### Main app component ##### */
/* ############################## */

class WrappedApp extends Component {
  constructor(props) {
    super(props);
    this.state = {
      filterText: "",
      favourites: [],
    };
  }

  // update filterText in state when user types
  filterUpdate(value) {
    this.setState({
      filterText: value,
    });
  }

  // add clicked name ID to the favourites array
  addFavourite(id) {
    const newSet = this.state.favourites.concat([id]);
    this.setState({
      favourites: newSet,
    });
  }

  // remove ID from the favourites array
  deleteFavourite(id) {
    const { favourites } = this.state;
    const newList = [...favourites.slice(0, id), ...favourites.slice(id + 1)];
    this.setState({
      favourites: newList,
    });
  }

  render() {
    const hasSearch = this.state.filterText.length > 0;
    return (
      <div>
        <header>
          <Greeting />
          <Search
            filterVal={this.state.filterText}
            filterUpdate={this.filterUpdate.bind(this)}
          />
        </header>
        <main>
          <ShortList
            data={this.props.data}
            favourites={this.state.favourites}
            deleteFavourite={this.deleteFavourite.bind(this)}
          />

          <TagsList
            data={this.props.data}
            filter={this.state.filterText}
            favourites={this.state.favourites}
            addFavourite={this.addFavourite.bind(this)}
          />
          {/* 
            Show only if user has typed in search.
            To reset the input field, we pass an 
            empty value to the filterUpdate method
          */}
          {hasSearch && (
            <button onClick={this.filterUpdate.bind(this, "")}>
              Clear Search
            </button>
          )}
        </main>
      </div>
    );
  }
}

export default WrappedApp;

这是我的index.js

import React from "react";
import ReactDOM from "react-dom";
import * as serviceWorker from "./serviceWorker";
import { ApolloProvider } from "@apollo/react-hooks";
import { client, GQLTags, GQLFunc } from "./graphclient";
import WrappedApp from "./WrappedApp";

/* ############################ */
/* ##### Single tag ##### */
/* ############################ */

ReactDOM.render(
  <ApolloProvider client={client}>
    <GQLFunc callingApp={WrappedApp} />
  </ApolloProvider>,
  document.getElementById("root")
);
    

概述最初加载WrappedApp时,会将查询发送到GraphQL API以获取数据(标签)。完成此操作后,用户可以通过单击...

reactjs graphql apollo hasura
1个回答
1
投票

可以很简单

© www.soinside.com 2019 - 2024. All rights reserved.