Переписать и оптимизировать React‑компоненты

Подписка scroll в теле App создаётся на каждом рендере и никогда не удаляется. Для прилипающей панели обычно достаточно position: sticky; счётчик обновляйте функционально, повторяющиеся Item создайте из списка.

Короткий ответ

Что ответить на собеседовании

Подписка scroll в теле App создаётся на каждом рендере и никогда не удаляется. Для прилипающей панели обычно достаточно position: sticky; счётчик обновляйте функционально, повторяющиеся Item создайте из списка.

Подробный разбор

Ответ с пояснениями

Условие

Выполнить рефакторинг представленного кода, устранив прямое взаимодействие с DOM и улучшив структуру компонентов.

App.tsx

import React, { useState } from "react";
import "./styles.css";
import Item from "./Item";

export default function App() {
  const [count, setCount] = useState(0);
  window.addEventListener("scroll", () => {
    const { scrollY } = window;
    if (scrollY > 100) {
      const topSection = document.querySelector<HTMLDivElement>(".top-section");
      if (topSection) {
        topSection.style.position = "absolute";
        topSection.style.top = scrollY + "px";
      } else {
        return;
      }
    } else {
      const topSection = document.querySelector<HTMLDivElement>(".top-section");
      if (topSection) {
        topSection.style.position = "static";
      } else {
        return;
      }
    }
  });

  return (
    <div className="App">
      <div className="block-wrapper">
        <div className="top-section">
          <button
            onClick={() => {
              alert(count);
            }}
          >
            Show count
          </button>
          <button
            onClick={() => {
              setCount(0);
            }}
          >
            Reset count
          </button>
        </div>
        <Item
          onAdd={() => {
            setCount(count + 1);
          }}
        />
        <Item
          onAdd={() => {
            setCount(count + 1);
          }}
        />
        <Item
          onAdd={() => {
            setCount(count + 1);
          }}
        />
        <Item
          onAdd={() => {
            setCount(count + 1);
          }}
        />
        <Item
          onAdd={() => {
            setCount(count + 1);
          }}
        />
        <Item
          onAdd={() => {
            setCount(count + 1);
          }}
        />
      </div>
    </div>
  );
}

Item.tsx

import React from "react";
import "./styles.css";

type Props = {
  onAdd: () => void;
};

export default function Item(props: Props) {
  return (
    <div className="block">
      <button className="btn" onClick={props.onAdd}>
        Add to cart
      </button>
    </div>
  );
}

Ответ

Подписка scroll в теле App создаётся на каждом рендере и никогда не удаляется. Для прилипающей панели обычно достаточно position: sticky; счётчик обновляйте функционально, повторяющиеся Item создайте из списка.

.top-section { position: sticky; top: 0; z-index: 1; background: white; }

Удалите весь window.addEventListener из тела компонента. В App:

const onAdd = React.useCallback(() => setCount(value => value + 1), []);
// В JSX вместо шести одинаковых блоков:
{Array.from({ length: 6 }, (_, index) => <Item key={index} onAdd={onAdd} />)}

Sticky ограничен своим контейнером и начинает прилипать при достижении края, не обязательно после глобальных 100px прокрутки. Если нужен именно этот порог, храните window.scrollY > 100 в состоянии через эффект с cleanup и меняйте CSS-класс декларативно. memo(Item) имеет смысл только при подтверждённой стоимости рендера и стабильных props.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее