【发布时间】:2020-09-27 16:13:11
【问题描述】:
概述
WrappedApp 最初加载时,会向 GraphQL API 发送查询以获取数据(标签)。
完成此操作后,用户可以通过单击TagsList 中的标签将项目添加到WrappedApp 中的ShortList(参见下面的屏幕截图)。
问题
我怎样才能点击TagsList 中的标签(即在下面的示例中点击了安全)以触发名为GQLSIMILARTAGS 的第二个GraphQL 查询并将结果呈现在ShortList 组件数据上方或最少 console.log GQLSIMILARTAGS 查询的结果? GQLSIMILARTAGS 接受一个变量,该变量是被点击并添加到 ShortList 的标签。
我尝试了什么?
我尝试修改WrappedApp 中的addFavourite 函数以使用带有useQuery(GQLSIMILARTAGS) 的新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.js 应用程序(编辑:根据@xadm 反馈更新为功能组件)。
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;
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>
);
}
}
这是我的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")
);
【问题讨论】:
-
如果查询与父子相关,则使用父子组件 - 只需在 GQLFunc 和 CallingApp 之间注入另一个组件级别。
标签: reactjs graphql apollo hasura