Reactjs 基于初始查询中的数据触发第二个GraphQL查询

Reactjs 基于初始查询中的数据触发第二个GraphQL查询,reactjs,graphql,apollo,hasura,Reactjs,Graphql,Apollo,Hasura,概述 当WrappedApp最初加载时,将向GraphQLAPI发送一个查询以获取数据(标记) 完成此操作后,用户可以通过单击标记列表中的标记将项目添加到WrappedApp中的短名单中(请参见下面的屏幕截图) 问题 我如何在TagsList中点击标记(即,在下面的示例中点击了安全性),以触发名为GQLSIMILARTAGS的第二个GraphQL查询,并在短名单组件数据或至少控制台上呈现结果。记录GQLSIMILARTAGS查询的结果GQLSIMILARTAGS接受一个变量,该变量将是单击并添加

概述

WrappedApp
最初加载时,将向GraphQLAPI发送一个查询以获取数据(标记)

完成此操作后,用户可以通过单击
标记列表中的标记将项目添加到
WrappedApp
中的
短名单中(请参见下面的屏幕截图)

问题

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

我试过什么?

我尝试修改
WrappedApp
中的
addfavorite
函数,用新的
GQLSIMILARTAGS
查询
useQuery(GQLSIMILARTAGS)
调用
GQLFunc
,但这可能不是最好的方法

这是Apollo GraphQL查询代码

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 };
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>
    );
  }
}
它可以简单到

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} />;
}
函数GQLFunc(props){
const{loading,error,data}=useQuery(GQLTAGS);
如果(加载)返回加载…

; if(error)返回错误:(

; //让CallingApp=props.CallingApp; //如果(数据)返回; 如果(数据)返回; } 功能GQLChild(道具){ const{loading,error,data}=useQuery(GQLSIMILARTAGS{ 变量:{ TagQueryResult:props.dataTag.something } }); 如果(加载)返回加载…

; if(error)返回错误:(

; 让CallingApp=props.CallingApp; //单独传递数据或合并为一个“数据”道具 如果(数据)返回; }
如果查询是父子相关的,那么使用父子组件-只需在GQLFunc和CallingApp之间插入另一个组件级别。用新数据源包装一些现成的应用程序就可以了。构建下一个复杂度“高于”的应用程序并搜索变通方法以从/向查询传递下一个数据/处理程序肯定不好。这是可能的(上下文或apollo本地状态)但这不是正确的方法。在正确的位置(应用程序组件内部)使用查询和突变重建应用程序。将
转换为功能组件,在内部使用
useQuery
,将
filterText
作为查询变量传递……但是(为了避免其他问题/复杂性)您应该传递一个/主变量-
,其中
使用
filterText
值构建的复杂条件对象)…
useMutation
(用于添加喜爱的突变)可以放置在
中,也可以放置在
中(无需传递
addFavorite
处理程序)…这一切都要看情况而定-数据获取/呈现/更新的位置即使是POC,也不应该朝这个方向走得更远,这将使简单的事情变得过于复杂。“失败快,成功快”我已将
WrappedApp
转换为函数组件并更新了问题中的代码。您能告诉我下一步要做什么吗?假设开始情况下,wrapper
读取标记并呈现
…您将标记作为
道具。数据
…下一步…
使用查询(GQLSIMILARTAGS)
(现在已硬编码)在
…中,它将获取一些具有类似项的
数据
…您可以传递到某个子组件中。
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")
);
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} />;
}