首页 > 解决方案 > 尝试在单击 React 时更改组件数组时重新渲染过多

问题描述

我是 React 的新手,我正在尝试使用钩子来生成组件列表,然后当单击按钮时,使用不同参数从另一个组件列表中更改该组件列表。我不确定我做错了什么。我已经阅读了 React 的文档并在 StackOverflow 中进行了检查。我得到一个无限循环,许多重新渲染。

但据我了解,首先我为 generateComponents() 设置一个值,它返回菜单名称下的组件列表,然后我使用菜单呈现该组件列表,但如果我按下按钮,那么它将切换 changeMenu将使用另一个参数将菜单变量更改为 generateComponents(),这也应该更新组件...

谢谢你的耐心!

function Menu(props) {
    const [menu, changeMenu] = useState(generateComponents("chivito"));

    function generateComponents(i) {
        return data[i].map((i) => (
            <Col key={i.key}>
                <Food
                    title={i.title}
                    subtitle={i.subtitle}
                    price={i.price}
                    url={i.url}
                    key={i.key}
                />
            </Col>
        ));
    }

    return (
        <>
            <button
                type="button"
                onClick={changeMenu(generateComponents("pack"))}
            >
                Chivito
            </button>

            <Container>
                <Row>{menu}</Row>
            </Container>
        </>
    );
}

export default Menu;

标签: javascriptreactjs

解决方案


当你这样做时,onClick={changeMenu(generateComponents("pack"))}你在渲染期间立即调用 changeMenu,这会导致状态更新,导致重新渲染,导致它们被再次调用,导致状态更新,导致重新渲染......</p>

onClick 应该是一个函数,你给它调用函数的结果。试试onClick={() => changeMenu(generateComponents("pack"))}吧。


如果我们将其与标记和 jsx 隔离开来,可能更容易看出区别。考虑以下点击处理函数:

function clickHandler () {
  return 'banana'; // arbitrary return value
}

您正在有效地执行此操作:

const onClick = clickHandler();
// onClick is now 'banana'

与此相反:

const onClick = clickHandler;
// onClick is now the clickHandler function itself

JSX 等价物是:

<button onClick={clickHandler}>

当然,这个问题是你不能传递参数。

参数传递问题有一些解决方案,但最直接的方法是创建一个新的匿名箭头函数,该函数使用特定参数调用处理程序:

const onClick = () => clickHandler(arg1, arg2, arg2)
// onClick is a new function that just calls the handler with arguments

应用于您的代码,它看起来像这样:

<button onClick={() => changeMenu(generateComponents("pack"))}>

您可能不想使用的替代方案:

你也可以绑定参数或创建一个返回函数的函数,但最终你会在同一个地方结束,你可以在下面看到匿名箭头函数是最简单的。

const onClick = clickHandler.bind(null, arg1, arg2)
// new function that will receive arg1 and arg2 when invoked
function makeHandler(arg1, arg2) {
  return function () {
    clickHandler(arg1, arg2);
  }
}

const onClick = makeHandler('foo', 'bar');
// new function that calls clickHandler('foo', 'bar')

推荐阅读