민프

[React][TypeScrpit] react-router-dom v6 - Link를 사용하여 화면 간 데이터 이동을 해보자 (state, useLocation()) 본문

[React]

[React][TypeScrpit] react-router-dom v6 - Link를 사용하여 화면 간 데이터 이동을 해보자 (state, useLocation())

민프야 2023. 1. 28. 00:03

화면 간 데이터 이동 방법은 앞서 포스팅 한 useParams으로 파라미터 값을 얻어서 할 수도 있고, props로 데이터를 보낼수도 있는데 이번에는 Link를 이용한 데이터 이동을 해보려고 한다. 

https://reactrouter.com/en/main/components/link#state

 

Link v6.8.0

This is the web version of . For the React Native version, go here. Type declarationdeclare function Link(props: LinkProps): React.ReactElement; interface LinkProps extends Omit< React.AnchorHTMLAttributes , "href" > { replace?: boolean; state?: any; to: T

reactrouter.com

공식문서를 보면

path에 대한 state값을 넣어 상태 저장 값을 설정하고 이 값은 'useLocation()' 으로 받을 수 있다고 나온다. 한번 해보자

import { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import styled from "styled-components";

const Container = styled.div`
    padding: 0px 20px;
    max-width: 480px;
    margin: 0 auto;
`;

const Header = styled.header`
height:10vh;
display: flex;
justify-content: center;
align-items: center;
`;

const CoinsList = styled.ul``;

const Coin = styled.li`
    background-color: white;
    color:${props=>props.theme.bgColor};
    margin-bottom: 10px;
    border-radius: 10px;
    cursor: pointer;
    a{
        padding:20px;
        align-items: center;
        transition: color 0.1s ease-in;
        display: flex;
    }
    &:hover{
        a{
            color:${(props)=> props.theme.accentColor}
        }
    }
`;

const Title = styled.h1`
font-size: 48px;
  color:${props => props.theme.accentColor};
`;

const coins = [
    {
        id: "btc-bitcoin",
        name: "Bitcoin",
        symbol: "BTC",
        rank: 1,
        is_new: false,
        is_active: true,
        type: "coin",
    },
    {
        id: "eth-ethereum",
        name: "Ethereum",
        symbol: "ETH",
        rank: 2,
        is_new: false,
        is_active: true,
        type: "coin",
    },
    {
        id: "hex-hex",
        name: "HEX",
        symbol: "HEX",
        rank: 3,
        is_new: false,
        is_active: true,
        type: "token",
    },
]

const Loader = styled.span`
    text-align: center;
    display: block;
`;

const Img = styled.img`
    width: 25px;
    height: 25px;
    margin-right: 10px;

`;


interface CoinInterface{
    id: string,
    name: string,
    symbol: string,
    rank: number,
    is_new: boolean,
    is_active: boolean,
    type: string,
}

function Coins(){
    const [coins, setCoins] = useState<CoinInterface[]>([]);
    const [loading, setLoading] = useState(true);
    useEffect(()=>{
        
        (async()=>{
            const response = await fetch("https://api.coinpaprika.com/v1/coins");
            const json = await response.json();
            setCoins(json.slice(0,100))
            setLoading(false);
        })();
    },[]);
    
    return (
        <Container>
            <Header>
                <Title>코인</Title>
            </Header>
            {loading ? <Loader>Loading...</Loader>:(
            <CoinsList>
                {coins.map((coin) =>
                (
                <Coin key={coin.id}>
                    <Link to={`/${coin.id}`} state={coin.name}>
                         <Img src={`https://coinicons-api.vercel.app/api/icon/${coin.symbol.toLocaleLowerCase()}`}/>
                        {coin.name} &rarr;
                    </Link>
                </Coin>)
                )
                }
            </CoinsList>
            )}
        </Container>
    );
}

export default Coins;
import { useLocation, useParams } from "react-router-dom";
import styled from "styled-components";

const Title = styled.h1`
  color:${props => props.theme.accentColor};
`;
function Coin(){
      //파라미터 값 가져오기
      const { coinId } = useParams();
      //state 값 가져오기
      const location = useLocation();
      console.log(location)
      return <Title>Coin: {coinId}</Title>
}

export default Coin;

Link state로 정보를 보내주고 useLocation() 으로 정보를 받아와서 log를 찍어보니 잘 적용된 것을 확인할 수 있었다. 

useLocation()에서 type을 지정하고 state만 따로 보고싶으면 interface로 type을 지정해줘야한다. 

import { useLocation, useParams } from "react-router-dom";
import styled from "styled-components";



const Title = styled.h1`
  color:${props => props.theme.accentColor};
`;

interface RouteState{
  name:string;
}

function Coin(){
      //파라미터 값 가져오기
      const { coinId } = useParams();
      //state 값 가져오기
      const location = useLocation();
      const name = location.state as RouteState;

      console.log(name)
      return <Title>Coin: {coinId}</Title>
}

export default Coin;

interface를 지정해주고 useLocation()으로 가져온 값에다 적용해주면 된다.

이렇게 되면 꼭 이전 페이지에서 클릭 후 state를 보내줘야만 접근이 가능하다

따라서 이 부분도 필요한 부분에 잘 사용하면 이전 페이지에서 받은 정보로 다음페이지를 구현할 수도 있을 것 같다. 

Comments