将字符串变量prop传递给useQuery函数

时间:2020-06-14 10:20:29

标签: reactjs graphql react-apollo apollo-client

概述

应用最初会查询GraphQL API,并使用TagsList呈现“标记”(字符串)。

然后用户可以单击一个标签,然后将该标签传递到ShortList并进行渲染。

interface

我要做什么?

我有另一个名为GQLSIMILARTAGS的GraphQL查询,它接受一个字符串变量,并在useQuery中使用GQLFuncSecond进行调用。我想在用户点击其中一个标签时触发此操作。

我知道查询可以像下面这样用硬编码的searchLabel作为变量来传递。

<GQLFuncSecond searchLabel={"cloud"} />

问题

当用户从data.tag.label单击标签时,如何将字符串(useQuery传递到此TagsList变量中。

我不知道如何将用户选择的标签(添加到ShortList时)传递到我的GQLFuncSecond函数中。

例如,我应该在GQLFuncSecond中呼叫ShortList吗?我该怎么办?

主应用

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

  function GQLFuncSecond(props) {
    const { loading, error, data } = useQuery(GQLSIMILARTAGS, {
      variables: { search_label: props.searchLabel },
    });
    if (loading) return <p>Loading...</p>;
    if (error) return <p>Error :(</p>;

    if (data) return <RelatedTagData data={data.tag} />;
  }

  // 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) => {
    const newList = [...favourites.slice(0, id), ...favourites.slice(id + 1)];
    setFavourites(newList);
  };

  return (
    <div>
      <main>
        <GQLFuncSecond searchLabel={"cloud"} />
        <ShortList
          data={props.data}
          favourites={favourites}
          deleteFavourite={deleteFavourite}
        />

        <TagsList
          data={props.data}
          favourites={favourites}
          addFavourite={addFavourite}
        />
      </main>
    </div>
  );
}

export default WrappedApp;

组件

import React, { useState } from "react";
import { useQuery } from "@apollo/react-hooks";
import { GQLSIMILARTAGS } 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>
);

const RelatedTagData = ({ data }) => (
  <div>
    <ul>{data[0].tag_related_counts[0].other_label}</ul>
    <ul>{data[0].tag_related_counts[1].other_label}</ul>
    <ul>{data[0].tag_related_counts[2].other_label}</ul>
    <ul>{data[0].tag_related_counts[3].other_label}</ul>text 
  </div>
);

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

const ShortList = ({ favourites, data, deleteFavourite, GQLFuncSecond }) => {
  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, addFavourite }) => {
  // Gather list of tags
  const tags = data
    // filtering out the tags that...

    .map((tag, i) => {
      return (
        <Tag
          id={tag.id}
          key={i}
          info={tag}
          handleFavourite={(id) => addFavourite(id)}
        />
      );
    });

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

GraphQL代码

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($search_label: String!) {
    tag(
      where: { tag_related_counts: { search_label: { _eq: $search_label } } }
      distinct_on: id
    ) {
      label
      tag_related_counts(order_by: { count: desc }) {
        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, GQLFuncSecond, GQLSIMILARTAGS };

2 个答案:

答案 0 :(得分:1)

暂时忘记自己拥有的东西...

您应传递与服务器中定义的查询形状匹配的变量

...这种形状看起来如何?您可以在graphiql文档中阅读它

...如果tag查询期望使用where参数,那么您应该传递where变量(无论是字符串还是复杂对象-在这种情况下),只有一个变量...

看看“根”变量whereorder_bydistinct_on-在graphiql文档中为tag查询定义的所有“输入类型”。

您不仅应该用一些[随机]'deeper'/'internal'变量替换某些查询/参数元素,它可以工作,但很快就可以处理,糟糕的DX。

您应该使用where(在这种情况下为prop)准备search_label对象,并将where作为变量传递。不难猜测您的查询应如下所示:

query someNameForRelatedTagsQuery($where: where) {
  tag( where: $where ) {
    id
    label

传递给查询的变量对象:

const vars = {
  where: { 
    tag_related_counts: { 
      search_label: { 
        _eq: props.search_label
} } } };

useQuery之前定义,在useQuery选项{ variables: vars }(第二个参数)中使用...变量对象也可以在惰性查询调用中使用。

它与早期的“工作”硬编码查询有何关系? -相同的结构,其他位置。

答案 1 :(得分:0)

我现在可以使用这种方法将字符串(data.tag.label)传递到useQuery变量中。它奏效,但很高兴听到任何更好的方法。

useState存储字符串标签数据

const [strfavourites, setstrFavourites] = useState([]);

ShortList中单击标签时将触发的功能

  const addstrFavourite = (id) => {
    const newSet = strfavourites.concat([id]);
    setstrFavourites(newSet);
  };

addstrFavourite添加到ShortList组件中:

 handleFavourite={(id) =>
          addstrFavourite(data.find((tag) => tag.id === fav))

如果useQuery长度> 0,则仅调用strfavourites函数

const hasstrFavourites = strfavourites.length > 0; 


 {hasstrFavourites &&
      strfavourites.map(function (d) {
        return <GQLFuncSecond key={d.label} searchLabel={d.label} />;
      })}