Реагируйте, используя ссылки для прокрутки при выборе из раскрывающегося списка

Хорошо, я пытаюсь создать раскрывающийся список, и при выборе элемента страница должна прокручиваться до определенного раздела (ссылка).

У меня есть несколько элементов div с одной и той же ссылкой (поскольку у меня более 30 элементов div, для которых требуется ссылка).

const SettingView = () => {
    const selectedItem = "el2"; // This is temporarily as it will be the item from a dropdown
    const ref = useRef<HTMLDivElement[]>([]);
    const filterRef = (el: HTMLDivElement) => ref.current.push(el);

    return (
        <>
            for (let item of sortedRows) {
                <div ref = {filterRef} id = {item.some.name}>{item.text}</div>
            }
        </>
    )
}

export default SettingView;

Таким образом, при нажатии кнопки он должен найти ссылку div, имеющую идентификатор из selectedItem, и прокрутить до него.

Как бы я это сделал?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
128
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Этого можно добиться, используя метод ScrollIntoView() для ссылки выбранного элемента. Вот как вы можете изменить свой компонент SettingView для достижения этой функциональности:

import React, { useRef } from 'react';

const SettingView = () => {
    const selectedItem = "el2";
    const ref = useRef<HTMLDivElement[]>([]);
    const filterRef = (el: HTMLDivElement) => ref.current.push(el);

    const scrollToRef = (ref: React.RefObject<HTMLDivElement>, id: string) => {
        const selectedRef = ref.current.find(item => item.id === id);
        if (selectedRef) {
            selectedRef.scrollIntoView({ behavior: 'smooth', block: 'start' });
        }
    };

    React.useEffect(() => {
        scrollToRef(ref, selectedItem);
    }, [selectedItem]);

    return (
        <>
            <div ref = {filterRef} id = "el1">Some Text</div>
            <div ref = {filterRef} id = "el2">Some Text2</div>
            <div ref = {filterRef} id = "el3">Some Text3</div>
            <div ref = {filterRef} id = "el4">Some Text4</div>
        </>
    );
}

export default SettingView;

В этом коде: Функция ScrollToRef принимает массив ссылок и идентификатор выбранного элемента. Он находит ссылку с соответствующим идентификатором и прокручивает ее в поле зрения с помощью функции ScrollIntoView() с опциями плавного поведения и начиная с начала блока. Хук useEffect используется для запуска эффекта прокрутки при каждом изменении selectedItem.

Вы сгенерировали этот ответ с помощью такого инструмента, как ChatGPT?

0stone0 22.02.2024 14:08

Если вы визуализируете свои кнопки с помощью map(), что должно быть нормально, поскольку отличается только идентификатор, тогда вы можете использовать итератор map, чтобы использовать его в качестве идентификатора.

Затем, нажав кнопку, получите этот индекс в массиве ref.current и вызовите (например) scrollIntoView() по нему.


Пример:

  • Нажмите на кнопку, чтобы вызвать scrollIntoView по этому поводу
  • Нажмите на самую верхнюю (настоящую) кнопку, чтобы вызвать scrollIntoView по индексу 50

const { useState, useRef } = React;

const SettingView = () => {

    const ref = useRef([]);
    
    let sortedRows = [
        { name: 'Foo', text: 'Bar' }
    ];
    
    // Add 99 other rows to sortedRow as debug values
    sortedRows = sortedRows.flatMap(i => Array(99).fill(i));
    
    const onButtonClick = (i) => {
        console.info('Clicked on ', i);
        if (ref.current[i]) {
            ref.current[i].scrollIntoView();
        }
    }
    
    return (
      <React.Fragment>
        <button onClick = {() => onButtonClick(50)}>Scroll to Button #50</button>
        
        {sortedRows.map((row, i) => {
            const { name, text } = row;
            
            return (
                <div onClick = {() => onButtonClick(i)} ref = {el => ref.current[i] = el} id = {"el" + i}>
                    Button {i} - {text}
                </div>
            );
            
        })}
      </React.Fragment>
     );
}

ReactDOM.render(<SettingView />, document.getElementById("react"));
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id = "react"></div>

Спасибо за ваш ответ. Я не использую индексы, так как раскрывающееся значение представляет собой строку. Он должен совпадать с ссылкой на любой из элементов div.

udarts 22.02.2024 14:47

НЕ уверен, что вы пытаетесь сказать, не имеет значения, что ваши значения являются строками. Все равно лучше визуализировать эти параметры через цикл, что касается DRY.

0stone0 22.02.2024 14:48

Элементы div находятся внутри цикла (сгенерированного из массива), так как внутри этих элементов отображается больше данных, но это не имеет значения.

udarts 22.02.2024 14:52

Ну, видимо, это актуально, ха-ха. Я также рендерю из массива, поэтому не знаю, что у вас не работает.

0stone0 22.02.2024 14:54

Я обновил свой ответ, чтобы также использовать массив объектов для отображения кнопок. Надеюсь, это прояснит ситуацию.

0stone0 22.02.2024 15:01

Еще раз спасибо, я попробовал этот пример, он показывает ошибку в этой части: «ref.current[i]» Введите «HTMLdivElement | null» не может быть присвоен типу «никогда». Тип «ноль» не может быть присвоен типу «никогда».

udarts 22.02.2024 15:11

Я не уверен, что может быть причиной этого, я не эксперт по машинописному тексту. Я удалил синтаксис машинописного текста из своего ответа, чтобы его можно было запустить в фрагменте stackoverflow. Проверьте еще раз, если вы обнаружите какую-либо разницу между ними. ИЛИ, возможно, обновите свой вопрос с помощью текущей попытки.

0stone0 22.02.2024 15:16
Ответ принят как подходящий

https://stackblitz.com/edit/stackblitz-starters-tuw9cm?file=src%2FApp.tsx

import { FC, useEffect, useRef, useState } from 'react';

const Div = ({ text, isActive }) => {
  const ref = useRef<any>();
  useEffect(() => {
    if (isActive) {
      ref.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [isActive]);
  return (
    <div
      ref = {ref}
      style = {{
        background: isActive ? '#006699' : '#dddddd',
        height: '200px',
        margin: '10px',
      }}
    >
      {text}
    </div>
  );
};

export const App: FC<{}> = () => {
  const data = [1, 2, 3, 4, 5, 6, 7];
  const [activei, setActivei] = useState(5);
  return (
    <div>
      <div>
        {data.map((item) => (
          <div
            onClick = {() => {
              setActivei(item);
            }}
            key = {item}
          >
            {' '}
            {item}{' '}
          </div>
        ))}
      </div>
      {data.map((item, index) => (
        <Div isActive = {item === activei} text = {item} key = {item} />
      ))}
    </div>
  );
};

Это было решение, которое сработало для меня лучше всего

udarts 23.02.2024 10:55

Другие вопросы по теме