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} />;
}