I have this implementation for a search filter using tags.
https://codesandbox.io/s/search-filter-tags-zgfcs?file=/src/Tags.tsx:622-626
I for the life of me cannot figure out why my setTags() method is not working in the handleChange function, but is working fine in the handleAllChange function.
Tags.tsx
import * as React from "react";
import { TagContext } from "./TagContext";
let AllTags = [
"Html",
"CSS",
"JavaScript",
"ReactJS",
"GitHub",
"TypeScript",
"Celebal"
];
const Tags = () => {
const { tags, setTags } = React.useContext(TagContext);
const [allChecked, setAllChecked] = React.useState(false);
// const [tags, setTags] = React.useState([] as string[]);
const handleAllChange = () => {
if (!allChecked) {
setTags(AllTags);
} else {
setTags([]);
}
setAllChecked(!allChecked);
};
const handleChange = (name: string) => {
let temp = tags;
if (temp.includes(name)) {
temp.splice(temp.indexOf(name), 1);
} else {
temp.push(name);
}
console.log("temp - ", temp);
setTags(temp);
};
React.useEffect(() => {
console.log("Tags - ", tags);
}, [tags]);
return (
<>
<h1>Filter Tags</h1>
<div className="tags-container">
<div className="w-fit p-2 m-2">
<button
className="p-1 border-2 border-black rounded font-semibold"
onClick={handleAllChange}
>
Apply All
</button>
</div>
{AllTags.map((tag, i) => {
return (
<div className="w-fit p-2 m-2" key={i}>
<input
className="mt-2"
type="checkbox"
value={tag}
name={tag}
onChange={(e) => handleChange(tag)}
checked={tags.includes(tag)}
/>
<label htmlFor={tag}>#{tag}</label>
</div>
);
})}
</div>
</>
);
};
export default Tags;
The tags, and setTags are coming from context API.
TagContext.tsx
import * as React from "react";
interface ITagContext {
tags: any;
setTags: any;
handleChange: (name: string) => void;
}
export const TagContext = React.createContext({} as ITagContext);
interface ITagProvider {
children: React.ReactNode;
}
export const TagProvider = ({ children }: ITagProvider) => {
const [tags, setTags] = React.useState([] as string[]);
const handleChange = (name: string) => {
debugger;
let tag = name;
let temp = tags;
if (temp.includes(tag)) {
temp.splice(temp.indexOf(tag), 1);
} else {
temp.push(tag.toString());
}
setTags(temp);
};
React.useEffect(() => {
debugger;
console.log("Tags in Context - ", tags);
}, [tags]);
return (
<TagContext.Provider value={{ tags, setTags, handleChange }}>
{children}
</TagContext.Provider>
);
};