You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何点击兄弟组件元素滚动到目标组件元素?

React字母导航滚动到对应国家列表项

我是ReactJS新手,开发了一个ReactJS/Vite应用,会获取并按字母顺序列出欧洲国家。我添加了一个包含可点击字母的侧边导航,希望点击某个字母时,应用能滚动到以该字母开头的第一个国家。目前我的SideNav和ListCountries组件是父组件App的兄弟组件。

App组件代码

function App() {
  useEffect(() => {
      fetch('https://restcountries.com/v3.1/region/europe')
          .then((data) => data.json())
          .then((data) => {
              setCountries(data);
               //do stuff..
              }
          });
  }, []);
  return (
      <div className='App'>
          <div className='row h-25 w-100 ps-5'>
            {/* 展示字母的组件 */}
              {alphabet &&
                  alphabet.map((letter) => (
                      <CardAlphabet
                          letter={alphabet}
                      />
                  )
              )}
          </div>
          <ul>
             {/* 按字母顺序展示国家的组件 */}
              {countries &&
                  countries.map((country, id) => (
                      key={id}
                      <Country
                          id={id}
                          name={country.name.common}
                      />
                  )
              )}
          </ul>
                  
      </div>
  );
}

CardAlphabet组件代码

export default function CardAlphabet(props) {
    return (
        <div className='col-lg-2'>
            <span
                className='some-classes'>
                {props.letter}
            </span>
        </div>
    );
}

Country组件代码

import { useEffect, useRef } from 'react';
import { useInView } from 'framer-motion';
import { useCountryStore } from './Cards/Store';
import classNames from 'classnames';

export const Country = (props) => {
    const ref = useRef();
    const isInView = useInView(ref, { margin: '-50% 0px -50% 0px' });
    const id = props.id;
    const countryStore = useCountryStore();
    const firstLetter = props.dataFirstLetter;

    useEffect(() => {
        if (isInView) {
            countryStore.setInViewCountry(id);
        }
        if (!isInView && countryStore.inViewCountry === id) {
            countryStore.setInViewCountry(null);
        }
    }, [isInView, id]);

// HandleClick用于点击国家时滚动到该元素,与当前问题无关
    const handleClick = () => {
        ref.current?.scrollIntoView({
            behavior: 'smooth',
            block: 'center',
            inline: 'center',
        });
    };

    return (
        <li
            onClick={handleClick}
            ref={ref}
            datafirstletter={firstLetter}
            className={classNames(
                'some-classes' + props.id,
                isInView ? 'text-active' : ''
            )}>
            
            <p className={classNames(isInView ? 'text-active' : '')}>{props.name}</p>
        </li>
    );
};

我尝试给每个国家元素添加了带有其首字母的data属性,但不知道如何从兄弟组件访问该属性,以及如何滚动到指定data属性的元素,希望得到解决思路。


解决方法

我解决了这个问题!具体实现步骤如下:

  1. 推导每个国家名称的首字母,传递为规范的data-first-letter属性给Country组件:
export const Country = (props) => {
  // 从国家名称提取首字母并转大写
  const firstLetter = props.name.charAt(0).toUpperCase();
  
  return (
        <li
            data-first-letter={firstLetter}
            className="some-classes">
            <p>{props.name}</p>
        </li>
    );
};
  1. 在App组件中定义滚动函数,通过点击事件传递给CardAlphabet组件:
function App() {
  function scrollToFirstLetter(targetLetter) {
        const targetElement = document.querySelector(`[data-first-letter='${targetLetter}']`);
        if (targetElement) {
            targetElement.scrollIntoView({
                behavior: 'smooth',
                block: 'center',
                inline: 'center',
            });
        }
    }

  // ... 其他逻辑(获取国家数据等)

  return(
       <div className='App'>
          <div className='row h-25 w-100 ps-5'>
              {alphabet &&
                  alphabet.map((letter) => (
                      <CardAlphabet
                          key={letter}
                          onClick={() => scrollToFirstLetter(letter)}
                          letter={letter}
                          presentLetter={presentSubNames}
                      />
                  )
              )}
          </div>
          {/* 国家列表渲染部分 */}
       </div>
  )
}

通过上述方式,就能获取导航中被点击的字母,定位到对应首字母的第一个国家元素,并平滑滚动到该位置。

内容的提问来源于stack exchange,提问作者Bagdadi7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:35:21