-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfilterCategoryNotes
More file actions
183 lines (150 loc) · 6.67 KB
/
filterCategoryNotes
File metadata and controls
183 lines (150 loc) · 6.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
Sure, here's an example of how to filter resources by category title using next.js, react, graphql-request, and the RESOURCE_BY_CATEGORY query:
1. Import the GraphQLClient class from graphql-request and create a client instance:
import { GraphQLClient } from'graphql-request';
const graphQLClient = new GraphQLClient(process.env.GRAPHQL_ENDPOINT);
- You'll need to replace process.env.GRAPHQL_ENDPOINT with the actual endpoint URL of your GraphQL API.
2. Define the GraphQL query for retrieving the data. Include any variables needed for filtering. For example:
query RESOURCE_BY_CATEGORY($title: String!)
{
resources(where: {category_some: { title_contains:$title } })
{
id
title
url
content { html }
image { altText
url
}
}
}
3. Create a state variable for the category title, and a function to update it:
import { useState } from'react';
function ResourceList() {
const [categoryTitle, setCategoryTitle] = useState('');
async functionfetchResourcesByCategoryTitle(title) {
const data = awaitgraphQLClient.request(RESOURCE_BY_CATEGORY, { title, });
setResources(data.resources); }
// ...
}
4.Render a text input for the category title, and call fetchResourcesByCategoryTitle when the input value changes:
function ResourceList() {
// ...
return (
<div>
<input type="text"value={categoryTitle} onChange={(e) => {
setCategoryTitle(e.target.value); fetchResourcesByCategoryTitle(e.target.value);
}}
/>
<ul>{resources.map((resource) => (
<li key={resource.id}>
<h2>{resource.title}</h2>
<p>{resource.url}</p>
<div dangerouslySetInnerHTML={{__html: resource.content.html }} >
<img src={resource.image.url}
alt={resource.image.altText} />
</li>
))}
</ul>
</div>
);
}
Note that we're using the dangerouslySetInnerHTML attribute to render the HTML content.
5. Optional: Add a "clear" button that resets the category state:
function ResourceList() {
// ...
function fetchAllResources() {
setCategoryTitle('');
setResources([]); }
return (
<div>
<input type="text" value={categoryTitle} onChange={(e) =>{ s
etCategoryTitle(e.target.value); fetchResourcesByCategoryTitle(e.target.value); }} />
<button onClick={() =>fetchAllResources()}>Clear</button>
<ul> {resources.map((resource) => (
<li key={resource.id}>
<h2>{resource.title}</h2>
<p>{resource.url}</p>
<div dangerouslySetInnerHTML={{__html:resource.content.html}}
/>
<img src={resource.image.url} alt={resource.image.altText} />
</li>
))}
</ul>
</div>
); }
6.Pass in any required variables to the GraphQL query. For example:
const RESOURCE_BY_CATEGORY = gql` query RESOURCE_BY_CATEGORY($title: String!)
{ resources(where: { category_some: { title_contains: $title } }) {
//With Button
To filter resources by category using a button for each category, you'll need to modify the ResourceList component to add the category filter buttons and handle their click events.
Here's an example implementation:
import { useState } from 'react';
import { GraphQLClient } from'graphql-request';
const graphQLClient = new GraphQLClient(process.env.GRAPHQL_ENDPOINT);
const CATEGORIES_QUERY = gql`
query CATEGORIES_QUERY {
categories {
id
title
}
}
`;
const RESOURCE_BY_CATEGORY_QUERY = gql`
query RESOURCE_BY_CATEGORY($title: String!) {
resources(where: { category_some: { title_contains: $title } }) {
id
title
url
content { html }
image { altText
url }
}
}
`;
function ResourceList() {
const [categoryTitle, setCategoryTitle] = useState('');
const [categories, setCategories] = useState([]);
const [resources, setResources] = useState([]);
async functionfetchCategories() {
const data = awaitgraphQLClient.request(CATEGORIES_QUERY);
setCategories(data.categories); }
async functionfetchResourcesByCategoryTitle(title) {
const data = awaitgraphQLClient.request(RESOURCE_BY_CATEGORY_QUERY, { title, });
setResources(data.resources); }
function handleCategoryClick(title) {
setCategoryTitle(title);
fetchResourcesByCategoryTitle(title);
}
function handleClearClick() {
setCategoryTitle('');
setResources([]);
}
return (
<div>
<div>
{categories.map((category) => (
<button key={category.id}onClick={() =>
handleCategoryClick(category.title)}>
{category.title}
</button> ))}
<button onClick={handleClearClick}>Clear</button>
</div>
<input type="text" value={categoryTitle} onChange={(e) => {
setCategoryTitle(e.target.value);
fetchResourcesByCategoryTitle(e.target.value); }} />
<ul>{resources.map((resource) => (
<li key={resource.id}>
<h2>{resource.title}</h2>
<p>{resource.url}</p>
<div dangerouslySetInnerHTML={{__html:resource.content.html}} />
<img src={resource.image.url}
alt={resource.image.altText} />
</li>))}
</ul>
</div>
);
}
In this example, we added a new query to fetch all available categories and render a button for each category.
When a category button is clicked, it sets the category title state and fetches the resources for that category.
We also added a "Clear" button that resets the category state and clears the list of resources.
Note that we kept the original text input for filtering by category title, so you can filter resources by typing a keyword in the input field if you prefer.