最近我开始使用JSX元素语法来代替函数调用,因为这样让代码更加美观。但是它们看起来并不相同。很惊奇的是,在 App.js
文件中,函数调用会导致无限循环(并抛出错误),而 JSX 元素却可以正常工作。而在 Dashboard.js
文件中,函数调用可以完美地工作,但 JSX 元素会导致无限循环(但不会抛出错误):
//App.js
import React, { useEffect, useState, memo } from "react";
import { connect } from "react-redux";
import { getUser } from "../firebase/user";
import Dashboard from "./Dashboard";
import SignIn from "./SignIn";
import "../styles/Global.scss";
import "../styles/App.scss";
const AppComponent = ({ userId, getUser }) => {
useEffect(() => { getUser() }, []);
const [ content, setContent ] = useState("");
const Content = () => {
if (userId === undefined) {
return null;
}
if (userId) {
setContent("dashboard");
return <Dashboard />;
} else {
setContent("sign-in");
return <SignIn />;
}
};
return (
<div className={`content-wrapper ${content}`}>
<Content /> //works fine
{Content()} //throws error
</div>
)
};
const App = memo(AppComponent);
const mapStateToProps = ({
user: { userId }
}) => ({
userId
});
const mapDispatchToProps = {
getUser
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
//Dashboard.js
import React, { useEffect, memo } from "react";
import { connect } from "react-redux";
import { getUserData } from "../firebase/user";
import { selectProject } from "../actions/projects";
import { getItem } from "../tools/LocalStorage";
import { getProjectDetails } from "../firebase/projects";
import { selectPages } from "../actions/pages";
import { getPagesDetails } from "../firebase/pages";
import Pages from "./Pages";
import Projects from "./Projects";
import Artboard from "./Artboard";
import "../styles/Dashboard.scss";
const cachedProject = JSON.parse(getItem("selectedProject"));
const cachedPages = JSON.parse(getItem("selectedPages"));
const DashboardComponent = ({
userId,
clientId,
getUserData,
selectedProject = cachedProject,
selectedPages = cachedPages,
pagesWithDetails,
selectProject,
selectPages,
getProjectDetails,
getPagesDetails
}) => {
useEffect(() => {
getUserData(userId);
cachedProject && selectProject(cachedProject);
cachedPages && selectPages(cachedPages);
}, []);
useEffect(() => {
if (selectedProject && clientId) {
getProjectDetails(
clientId,
selectedProject
);
}
}, [selectedProject, clientId]);
useEffect(() => {
if (selectedPages && selectedProject && clientId) {
const withoutDetails = selectedPages.filter(pageId => (
!pagesWithDetails.includes(pageId)
));
getPagesDetails(
selectedProject,
withoutDetails
);
}
}, [selectedPages, selectedProject, clientId]);
const Content = () => {
if (!clientId) return null;
if (!selectedProject) {
return <Projects />;
}
if (!selectedPages) {
return <Pages />;
}
return <Artboard />;
};
return Content(); //worked good
return <Content /> //caused infinite loop
};
const Dashboard = memo(DashboardComponent);
const mapStateToProps = ({
user: {
userId,
clientId
},
projects: {
selectedProject
},
pages: {
selectedPages,
pagesDetails
}
}) => ({
userId,
clientId,
selectedProject,
selectedPages,
pagesWithDetails: Object.keys(pagesDetails)
});
const mapDispatchToProps = {
getUserData,
selectProject,
selectPages,
getPagesDetails,
getProjectDetails
};
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
我认为包装组件也是一个函数,并使用memo()
进行包装,这是一个重要的信息,但我仍然不理解为什么会发生上述情况。这两种语法背后的工作原理是什么,它们为什么不同?