为什么自定义钩子、上下文和useEffect会导致无限循环



为什么这个简单的代码会导致无限循环渲染Projects组件及其子组件(自然(,并且因为useEffect无穷循环访问firebase?使用已导入useProjects自定义挂钩的contextProvider管理状态。

自定义挂钩:

export const useProjects = () => {
const [projects, setProjects] = useState([]);
useEffect(() => {
const db = firebase
.firestore()
.collection("projects")
.where("userId", "==", "1234567890")
.orderBy("projectId")
.get();
db.then((result) => {
const allProjects = result.docs.map((project) => ({
docId: project.id,
...project.data(),
}));
if (JSON.stringify(allProjects) !== JSON.stringify(projects)) {
setProjects(allProjects);
}
}).catch((err) => {
console.log("useProjects error", err);
});
}, [projects]);
return { projects, setProjects };
};

项目组成部分:

const Projects = () => {
const [active, setActive] = useState(null);
const { setSelectedProject } = useSelectedProjectValue();
const { projects } = useProjectsValue();
return (
projects &&
projects.map((project) => (
<li
key={Math.random()}
className={
active === project.projectId
? "sidebar__project active"
: "sidebar__project"
}
>
<div
onClick={() => {
setActive(project.projectId);
setSelectedProject(project.projectId);
}}
>
<IndividualProject
className="individualProjectComp"
project={project}
/>
</div>
</li>
))
);
};

您在useEffect中设置项目状态,useEffect将项目本身视为依赖项,即使您在设置之前比较项目值,在字符串化值时发生的一些更改也会导致每次状态更新。

您可以通过不将项目作为依赖项添加到useEffect来避免这种情况,因为projects只在useEffect内部更新,而不会在的其他任何地方更新

export const useProjects = () => {
const [projects, setProjects] = useState([]);
useEffect(() => {
const db = firebase
.firestore()
.collection("projects")
.where("userId", "==", "1234567890")
.orderBy("projectId")
.get();
db.then((result) => {
const allProjects = result.docs.map((project) => ({
docId: project.id,
...project.data(),
}));
setProjects(allProjects);
}).catch((err) => {
console.log("useProjects error", err);
});
}, []);
return { projects, setProjects };
};