<Component />和Component()有什么区别?

4

最近我开始使用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()进行包装,这是一个重要的信息,但我仍然不理解为什么会发生上述情况。这两种语法背后的工作原理是什么,它们为什么不同?


无限循环的堆栈跟踪应该告诉你是哪个组件/函数。 - Rainbow
1个回答

4

为什么差异会导致在 React.createElement 处出现无限循环,而在函数调用时却不会? - Gergő Horváth
1
@GergőHorváth 很难确定在你的情况下是什么导致了无限循环,但你不应该在另一个组件的渲染方法中创建新组件。 - Tholle
1
令人惊讶的是,在另一种情况下,根据您的建议,我将JSX语法更改为函数调用,结果出现错误:Too many re-renders. React limits the number of renders to prevent an infinite loop. - Gergő Horváth
我使用完整的组件文件扩展了我的代码片段。 - Gergő Horváth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接