根据初始查询的数据触发第二个 GraphQL 查询 [英] Triggering a second GraphQL query based on data from initial query

查看:27
本文介绍了根据初始查询的数据触发第二个 GraphQL 查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

概述

WrappedApp 最初加载时,会向 GraphQL API 发送查询以获取数据(标签).

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

问题

如何点击 TagsList 中的标签(即在下面的示例中点击了安全性)以触发名为 GQLSIMILARTAGS 的第二个 GraphQL 查询并呈现结果高于 ShortList 组件数据或至少 console.log GQLSIMILARTAGS 查询的结果?GQLSIMILARTAGS 接受一个变量,它是被点击并添加到 ShortList 的标签.

我尝试了什么?

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

这是 Apollo GraphQL 查询代码.

graphclient.jsconst 客户端 = 新 ApolloClient({uri: "https://xxxx.herokuapp.com/v1/graphql",});const GQLTAGS = gql`{标签(order_by: { tag_related_counts_aggregate: { count: desc } }其中:{标签:{_nin:[无",空"]}}){ID标签tag_related_counts_aggregate {总计的 {数数}}}}`;const GQLSIMILARTAGS = gql`询问 {标签(其中:{ tag_related_counts: { search_label: { _eq: "security" } } }distinct_on: id){标签tag_related_counts {数数其他_标签搜索标签}}}`;函数 GQLFunc(props) {const { 加载,错误,数据 } = useQuery(GQLTAGS);if (loading) return <p>Loading...</p>;if (error) 返回 <p>Error :(</p>;让 CallingApp = props.callingApp;if (data) return ;}出口{客户端,GQLTAGS,GQLFunc};

这是主要的 WrappedApp.js 应用程序(根据@xadm 反馈更新为功能组件).

 function WrappedApp(props) {const [filterText, setfilterText] = useState("");const [收藏夹,设置收藏夹] = useState([]);//当用户输入时更新 filterText 的状态const filterUpdate = (value) =>{设置过滤器文本(值);};//将点击的姓名 ID 添加到收藏夹数组const addFavourite = (id) =>{const newSet = favourites.concat([id]);设置收藏夹(新集);};//从收藏夹数组中删除 IDconst deleteFavourite = (id) =>{//console.log(id);const newList = [...favourites.slice(0, id), ...favourites.slice(id + 1)];设置收藏夹(新列表);};const hasSearch = filterText.length >0;返回 (<div>{GQLSimilarFunc()}<标题><问候/><搜索 filterVal={filterText} filterUpdate={filterUpdate}/></标题><主要><短名单数据={道具.数据}收藏夹={收藏夹}simfunc={GQLSimilarFunc}/><标签列表数据={道具.数据}过滤器={过滤器文本}收藏夹={收藏夹}添加收藏夹={添加收藏夹}/>{/*仅在用户输入搜索时显示.要重置输入字段,我们传递一个filterUpdate 方法的空值*/}{hasSearch &&(<button onClick={() =>filterUpdate("")}>清除搜索)}</main>

);}导出默认的 WrappedApp;

WrappedApp

中使用的其他代码

import React, { Component, useState } from "react";从./graphclient"导入 { GQLSimilarFunc };/* ###########################*//* #####单标签##### *//* ###########################*/const Tag = ({ id, info, handleFavourite }) =>(<li className={info.count} onClick={() =>handleFavourite(id)}>{info.label} ({info.tag_related_counts_aggregate.aggregate.count}));/* ####################*//* #####候选名单##### *//* ####################*/const ShortList = ({ 收藏夹,数据,simfunc }) =>{const hasFavourites = favourites.length >0;const favList = favourites.map((fav, i) => {console.log(data.find((tag) => tag.id === fav).label);返回 (<标签id={i}键={i}info={data.find((tag) => tag.id === fav)}//handleFavourite={(id) =>删除收藏夹(id)}handleFavourite={() =>simfunc()}/*handleFavourite={GQLSimilarFunc(data.find((tag) => tag.id === fav).label)}*//>);});//console.log(data.find((tag) => tag.id === 4436));返回 (<div className="收藏夹"><h4>{有收藏夹?入围名单.点击删除..":点击标签将其列入候选名单.."}<ul>{favList}</ul>{有收藏夹&&<hr/>}

);};/* ########################## *//* #####标签列表##### *//* ########################## */const TagsList = ({ data, filter, favourites, addFavourite }) =>{常量输入 = 过滤器;//收集标签列表const 标签 = 数据//过滤掉那些....filter((tag, i) => {返回 (//...已经被收藏favourites.indexOf(tag.id) === -1 &&//...与当前搜索值不匹配!tag.label.indexOf(输入));})//...输出一个<名称/>每个名称的组件.map((tag, i) => {//console.log(tag.label);//只显示匹配当前输入字符串的标签返回 (<标签id={tag.id}键={i}信息={标签}handleFavourite={(id) =>添加收藏夹(id)}/>);});/* #####组件的输出##### */返回 <ul>{tags}</ul>;};/* ######################*//* ##### 搜索栏 ##### *//* ######################*///这里需要一个组件类//因为我们使用的是 `refs`类搜索扩展组件{使成为() {const { filterVal, filterUpdate } = this.props;返回 (<表格><输入类型=文本"参考 =过滤器输入"占位符=类型过滤.."//将输入值绑定到状态值={filterVal}onChange={() =>{过滤器更新(this.refs.filterInput.value);}}/></表单>);}}

这是我的index.js

从react"导入React;从react-dom"导入 ReactDOM;import * as serviceWorker from "./serviceWorker";从@apollo/react-hooks"导入{ ApolloProvider};从./graphclient"导入{客户端,GQLTags,GQLFunc};从./WrappedApp"导入WrappedApp;/* ##########################*//* #####单标签##### *//* ###########################*/ReactDOM.render(<ApolloProvider client={client}><GQLFunc callsApp={WrappedApp}/></ApolloProvider>,document.getElementById("root"));

解决方案

可以很简单

function GQLFunc(props) {const { 加载,错误,数据 } = useQuery(GQLTAGS);if (loading) return <p>Loading...</p>;if (error) 返回 <p>Error :(</p>;//让CallingApp = props.callingApp;//if (data) return ;if (data) return <GQLChild dataTag={data.tag} callsApp={props.callingApp}/>;}函数 GQLChild(props) {const { 加载,错误,数据 } = useQuery(GQLSIMILARTAGS, {变量:{someSimilarRequiredVariableFromTagQueryResult: props.dataTag.something}});if (loading) return <p>Loading...</p>;if (error) 返回 <p>Error :(</p>;让 CallingApp = props.callingApp;//单独传递数据或合并为一个 `data` propif (data) return ;}

Overview

When WrappedApp initially loads, a query is sent to the GraphQL API to fetch the data (Tags).

After this has completed a user can add an item to the ShortList in WrappedApp by clicking on a Tag in the TagsList (see screenshot below).

Question

How can I get this click of a Tag in the TagsList (i.e. security was clicked in the example below) to trigger the second GraphQL query named GQLSIMILARTAGS and render the result above the ShortList components data or at least console.log the result of the GQLSIMILARTAGS query? GQLSIMILARTAGS accepts a variable which would be the Tag that was clicked and added to ShortList.

What have I tried?

I tried modifying the addFavourite function in WrappedApp to call GQLFunc with the new GQLSIMILARTAGS query with useQuery(GQLSIMILARTAGS) but this may not be the best approach.

This is the Apollo GraphQL query code.

graphclient.js




const client = new ApolloClient({
  uri: "https://xxxx.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 {
    tag(
      where: { tag_related_counts: { search_label: { _eq: "security" } } }
      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 };

This is the main WrappedApp.js App (edit: Updated to function component as per @xadm feedback).

       function WrappedApp(props) {
  const [filterText, setfilterText] = useState("");
  const [favourites, setFavourites] = useState([]);

  // update filterText in state when user types
  const filterUpdate = (value) => {
    setfilterText(value);
  };

  // add clicked name ID to the favourites array
  const addFavourite = (id) => {
    const newSet = favourites.concat([id]);
    setFavourites(newSet);
  };

  // remove ID from the favourites array
  const deleteFavourite = (id) => {
    //console.log(id);
    const newList = [...favourites.slice(0, id), ...favourites.slice(id + 1)];
    setFavourites(newList);
  };

  const hasSearch = filterText.length > 0;
  return (
    <div>
      {GQLSimilarFunc()}
      <header>
        <Greeting />
        <Search filterVal={filterText} filterUpdate={filterUpdate} />
      </header>
      <main>
        <ShortList
          data={props.data}
          favourites={favourites}
          simfunc={GQLSimilarFunc}
        />

        <TagsList
          data={props.data}
          filter={filterText}
          favourites={favourites}
          addFavourite={addFavourite}
        />
        {/* 
            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={() => filterUpdate("")}> Clear Search</button>
        )}
      </main>
    </div>
  );
}

export default WrappedApp;

Other code used in WrappedApp

import React, { Component, useState } from "react";
import { GQLSimilarFunc } from "./graphclient";

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

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


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

const ShortList = ({ favourites, data, simfunc }) => {
  const hasFavourites = favourites.length > 0;
  const favList = favourites.map((fav, i) => {
    console.log(data.find((tag) => tag.id === fav).label);
    return (
      <Tag
        id={i}
        key={i}
        info={data.find((tag) => tag.id === fav)}
        //handleFavourite={(id) => deleteFavourite(id)}
        handleFavourite={() => simfunc()}
        /*handleFavourite={GQLSimilarFunc(
          data.find((tag) => tag.id === fav).label
        )}*/
      />
    );
  });
  //console.log(data.find((tag) => tag.id === 4436));

  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) => {
      //console.log(tag.label);
      // 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>
    );
  }
}

and this is my 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")
);

解决方案

It can be as simple as

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} />;
  if (data) return <GQLChild dataTag={data.tag} callingApp={props.callingApp} />;
}

function GQLChild(props) {
  const { loading, error, data } = useQuery(GQLSIMILARTAGS, {
    variables: {
      someSimilarRequiredVariableFromTagQueryResult: props.dataTag.something
    }
  });

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

  let CallingApp = props.callingApp;
  // pass data separately or combine into one `data` prop
  if (data) return <CallingApp dataSimilar={data} dataTag={props.dataTag} />;
}

这篇关于根据初始查询的数据触发第二个 GraphQL 查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆