LoginSignup
0
0

Reactでページ内遷移を実装する。(AnchorLinkを実装する)

Posted at

はじめに

表題通り、Reactでページ内遷移を実装します。
よくWebページで#値を元にページ内遷移ができるUIをどのように実装しているのだろうという興味のもと、今回実装してみました。

成果物

card_scroll.gif

ソースコード

ディレクトリ構成
├── src
│   ├── App.tsx
│   ├── components
│   │   ├── ListCard.tsx
│   │   ├── ListContainer.tsx
│   │   ├── hooks.tsx
│   │   └── type.ts
│   ├── index.tsx

ソースコード

App.tsx
import React from 'react';
import { ListContainer } from './components/ListContainer'

function App() {
  return (
    <ListContainer />
  );
}

export default App;
src/components/hooks.tsx
import { useEffect, useState } from "react"
import { ListItem } from "./type"

export const useCardScroll = () => {
    const [list, setList] = useState<ListItem[]>([]);

    useEffect(() => {
      const items = Array.from({ length: 100 }, (_, index) => ({
        id: `card${index + 1}`,
        title: `タイトル${index + 1}`,
        content: `コンテンツ${index + 1}`
      }));
      setList(items);
  
      const scrollToCard = () => {
        const hash = window.location.hash;
        if (hash) {
          const id = hash.replace('#', '');
          const element = document.getElementById(id);
          if (element) {
            element.scrollIntoView();
          }
        }
      };
  
      scrollToCard(); // コンポーネントのマウント時にスクロール
      window.addEventListener('hashchange', scrollToCard); // ハッシュ変更時にスクロール
  
      return () => {
        window.removeEventListener('hashchange', scrollToCard);
      };
    }, []);

    return { list }
}
src/components/ListCard.tsx
import { Card, CardContent, Typography } from '@material-ui/core'
import React from 'react';

export interface ListItem {
    id: string;
    title: string;
    content: string;
  }

export  const ListCard: React.FC<{ item: ListItem }> = ({ item }) => {
    const handleClick = () => {
      window.location.hash = item.id;
    };
    return (
      <Card id={item.id} style={{ margin: '10px', width: '200px' }} onClick={handleClick}>
        <CardContent>
          <Typography variant="h6">{item.title}</Typography>
          <Typography variant="body2">{item.content}</Typography>
        </CardContent>
      </Card>
    );
  };
src/components/ListContainer.tsx
import React from 'react';
import { ListItem } from './type'
import { ListCard } from './ListCard'
import { useCardScroll } from './hooks'

export const ListContainer: React.FC = () => {
    const { list } = useCardScroll();

  return (
    <div>
      {list.map((item: ListItem) => (
        <ListCard key={item.id} item={item} />
      ))}
    </div>
  );
};

src/components/type.ts
export type ListItem = {
    id: string;
    title: string;
    content: string;
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0