为什么上下文 api 提供的我的 setter 函数在句柄函数中不起作用
Why is my setter function provided by the context api not working in the handle function
我有这个使用标签的搜索过滤器的实现。
https://codesandbox.io/s/search-filter-tags-zgfcs?file=/src/Tags.tsx:622-626
我一辈子都弄不明白为什么我的 setTags() 方法在 handleChange 函数中不起作用,但在 handleAllChange 函数中却工作正常。
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;
标签和 setTags 来自上下文 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>
);
};
在您的 handleChange()
函数中,您使用了对 tags
数组的引用:
let temp = tags;
这意味着当您最终调用 setTags(temp);
时,引用没有改变并且您的 Tags
组件无法重新呈现。而是创建一个新数组:
let temp = [...tags];
我有这个使用标签的搜索过滤器的实现。
https://codesandbox.io/s/search-filter-tags-zgfcs?file=/src/Tags.tsx:622-626
我一辈子都弄不明白为什么我的 setTags() 方法在 handleChange 函数中不起作用,但在 handleAllChange 函数中却工作正常。
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;
标签和 setTags 来自上下文 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>
);
};
在您的 handleChange()
函数中,您使用了对 tags
数组的引用:
let temp = tags;
这意味着当您最终调用 setTags(temp);
时,引用没有改变并且您的 Tags
组件无法重新呈现。而是创建一个新数组:
let temp = [...tags];