@Narts

Есть ли отличия хранить JSX в функции или в константе?

привет! есть примерно такой компонент:
<Layout
        theme="transparent"
        before={(
          <LayoutGroup>
            <Item>item</Item>
            <Item>item</Item>
            <Item>item</Item>
            <Item>item</Item>
            <Item>item</Item>
            <Item>item</Item>
          </LayoutGroup>
        )}
        after={(
          <SideBar header={<Title size="large" icon={icon1}>Title</Title>}>
            inner
          </SideBar>
        )}
      >
        content
      </Layout>


это упрощенный пример компонента, для наглядности. смущает что компонент разрастается и становится нечитаемым. Решил вынести before и after в отдельные костанты. Есть два варианта: вынести код в константу или в стрелочную функцию:
function Home() {
  const before = (
    <LayoutGroup>
      <Item>item</Item>
      <Item>item</Item>
      <Item>item</Item>
      <Item>item</Item>
      <Item>item</Item>
      <Item>item</Item>
    </LayoutGroup>
  );

  const renderAfter = () => (
    <SideBar header={<Title size="large" icon={icon1}>Title</Title>}>
      inner
    </SideBar>
  );

  return (
    <Layout
      theme="transparent"
      before={before}
      after={renderAfter}
    >
      content
    </Layout>
  );
}


Объясните плиз, чем отличаются эти способы? Нигде не нашел информации по этому поводу. Склоняюсь к варианту renderAfter, тк можно будет обернуть в useMemo, чтобы избавиться от лишних ререндеров, но надо ли оно?
  • Вопрос задан
  • 162 просмотра
Пригласить эксперта
Ответы на вопрос 1
@romant094
Frontend-developer
Зависит от задачи и того, что у вас внутри компонента Layout.
renderAfter нужно вызывать так: after={renderAfter()} либо внутри компонента так сделать.
Функцию делать не рекомендую, т.к. при каждом ререндере она будет пересозаваться.
Я сам всегда использую вариант объявления констант в компоненте, чтобы минимизировать размер рендера.
В useMemo тоже смысла тут не вижу. Его стоит использовать для хранения результата тяжелых вычислений для минимизации нагрузки на браузер.

Пример
import { Divider } from '@mui/material'
import React, { FC, forwardRef } from 'react'

import { Typography, Button, Tooltip, Icon, Link } from '../../atoms'
import { Dropdown } from '../../molecules'
import { theme } from '../../theme'

import {
  SSectionBoxWrapper,
  SSectionBoxHeader,
  SSectionBoxContent,
  SSectionBoxHeaderSection,
  SSectionBoxDropdown,
  SSectionBoxSubtitle,
  SSectionBoxTitle,
  SSectionBoxTooltipIconWrapper,
  SSectionBoxSearchWrapper,
  SSectionBoxSearchInput,
  SSectionBoxSearchIcon,
} from './styles'
import { SectionBoxProps } from './types'

export const SectionBox: FC<SectionBoxProps> = forwardRef(({
  leadIcon,
  title,
  subTitle,
  tooltip,
  actionButtons,
  action,
  link,
  selectOptions,
  searchOptions,
  children,
  noChildrenText = 'Nothing here',
  withBackground,
  customComponent,
  withPaddings = true,
  showHeaderDivider = false,
  ...props
}, ref) => {
  const hasLeftSide = Boolean(leadIcon || title || subTitle || tooltip || actionButtons)
  const hasRightSide = Boolean(action || link || selectOptions || searchOptions || customComponent)

  const dropdownNode = leadIcon && <SSectionBoxDropdown {...leadIcon} />

  const titleNode = title && <SSectionBoxTitle>{title}</SSectionBoxTitle>

  const subtitleNode = subTitle && <SSectionBoxSubtitle>{subTitle}</SSectionBoxSubtitle>

  const tooltipNode = tooltip && (
    <Tooltip placement="top" {...tooltip}>
      <SSectionBoxTooltipIconWrapper>
        <Icon name="InfoOutlined" fontSize="small" />
      </SSectionBoxTooltipIconWrapper>
    </Tooltip>
  )

  const actionsNode =
    actionButtons &&
    actionButtons.length > 0 &&
    actionButtons.map((item, index) => (
      <Button {...item} key={index}>
        {item.label}
      </Button>
    ))

  const actionNode = action && <Button {...action}>{action.label}</Button>

  const linkNode = link && <Link {...link}>{link.label}</Link>

  const noChildrenNode = (
    <Typography align="center" fontStyle="italic" color={theme.palette.grey[500]} fontWeight={400}>
      {noChildrenText}
    </Typography>
  )

  const selectOptionsNode = selectOptions && <Dropdown {...selectOptions} />

  const searchNode = searchOptions && (
    <SSectionBoxSearchWrapper>
      <SSectionBoxSearchIcon name="Search" />
      <SSectionBoxSearchInput label="Search" variant="standard" autoComplete="off" {...searchOptions} />
    </SSectionBoxSearchWrapper>
  )

  const header = (hasLeftSide || hasRightSide) && (
    <SSectionBoxHeader $hasLeftSide={hasLeftSide} $hasRightSide={hasRightSide}>
      <SSectionBoxHeaderSection>
        {actionsNode}
        {dropdownNode}
        {titleNode}
        {subtitleNode}
        {tooltipNode}
      </SSectionBoxHeaderSection>
      <SSectionBoxHeaderSection>
        {actionNode}
        {linkNode}
        {searchNode}
        {selectOptionsNode}
        {customComponent}
      </SSectionBoxHeaderSection>
    </SSectionBoxHeader>
  )

  return (
    <SSectionBoxWrapper
      $withBackground={withBackground}
      $withPaddings={withPaddings}
      ref={ref}
      {...props}
    >
      {header}
      {showHeaderDivider && <Divider />}
      <SSectionBoxContent>{children ? React.Children.map(children, item => item) : noChildrenNode}</SSectionBoxContent>
    </SSectionBoxWrapper>
  )
})

export default SectionBox
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы