Ответы пользователя по тегу React
  • Есть ли отличия хранить JSX в функции или в константе?

    @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
    Ответ написан
    Комментировать
  • Как мне на 100% протестировать данный компонент?

    @romant094
    Frontend-developer
    Вам нужно проэмулировать сценарии, которые могут случиться при работе реального юзера с вашим проектом.
    Например, в этой ситуации я вижу такие кейсы:
    — компонент отрендерился, но данных нет
    — юзер нажал на кнопку, вызвана функция запроса, произошла ошибка, данных нет, компонента MainPage нет
    — юзер нажал на кнопку, вызвана функция запроса, данные пришли, компонент MainPage отрендерился

    Будет еще четвертый кейс для тестирования — вызов функции ping. Но это стоит делать в тесте компонента MainPage.
    Функцию запроса и ответы от сервера можно замокать.
    Ответ написан
    Комментировать
  • Как сделать плавную анимацию высоты React?

    @romant094
    Frontend-developer
    Используйте useRef вместо querySelector.
    Пример тут: https://codesandbox.io/s/beautiful-shape-8dm1ti?fi...
    Ответ написан
    Комментировать
  • React Select как изменить hover стили?

    @romant094
    Frontend-developer
    Там следующая структура:
    <div class="basic-single css-b62m3t-container">
      <div class="select__control css-1s2u09g-control">
       // ......
      </div>
    </div>

    Нужно добавить border-color внутреннему блоку при ховере.
    .select__control:hover {
        border-color: blue;
    }
    Ответ написан
    Комментировать
  • Делаю create-vk-mini-app, выдает ошибку?

    @romant094
    Frontend-developer
    Какая версия ноды у вас?
    Возможно, это решит вопрос: Fix the upstream dependency conflict, or retry this command with --force, or --legacy-peer-deps
    У вас в логе написано это.
    Еще нашел статью об этом: https://go.innoscripta.com/615eba813f727
    Ответ написан
    Комментировать
  • Какую админку выбрать для проекта на react + nodejs?

    @romant094
    Frontend-developer
    Если пишется фронт и бэк отдельно, то и админку можно написать с нуля. Это будет очень просто.
    Сделать роут на {domain}/admin, там поставить проверку на авторизацию и все.
    Ответ написан
    Комментировать
  • Как решить проблему рендера filter:drop-shadow в React?

    @romant094
    Frontend-developer
    Я бы рекомендовал заменить на box-shadow на мобилках, потому что просадка по перфомансу будет сильная, если браузер не поддерживает это.

    Вот тут описано, когда что лучше использовать.
    https://css-tricks.com/breaking-css-box-shadow-vs-...

    UPD смотрите, какие браузеры надо поддерживать и принимайте решение, использовать это или нет.
    https://caniuse.com/?search=drop-shadow
    Ответ написан
    Комментировать
  • Что лучше использовать Redux или Context?

    @romant094
    Frontend-developer
    Много статей на эту тему. Вот одна из них: https://habr.com/ru/post/419449/
    Но в общем и целом, как правильно замечено выше, зависит от целей.
    У обоих подходов есть как плюсы, так и минусы.
    Я бы ответил на вопрос так: если проект маленький (типа todo list), то context. Если большой, то нужен уже централизованный стейт менеджер.
    Ответ написан
    Комментировать
  • Как в React выполнить последовательно асинхронные функции?

    @romant094
    Frontend-developer
    Можно сделать так:
    const initCategories = async () => {
      try {
        const data = await getCategories()
        const collect = await getCollect(data)
        setCategories(data)
        setValues({ ...values, loaded: true })
      } catch (error) {
        setValues({ ...values, error })
      }
    }
    
    const getCollect = async data => {
      return await fetch('https://site.com')
    }

    Не стал переписывать все в точности, но суть, думаю, понятна.
    Ответ написан