CRYPTO Part.1

니니·2023년 5월 20일

#5.0~5.9

이번 강의부터는 react-route-dom(@type 포함)을 5.3.0 버전을 사용한다.


🚫ERROR🚫

그런데 export설정한 파일을 import 하는데 모듈을 찾을 수 없다는 에러가 발생했다.(시작부터 매끄럽게 되는거 하나도 없음 나만 이럼..?)

상대경로

./ : 현재파일
../: 상위파일

그냥 내가 바보였던 것


useParams : URL에서 가지고 오고 싶은 정보를 잡아낼 수 있게 해준다.

/:coinId : coinId로 페이지를 구분 짓겠다는 의미

const { coinId } = useParams<{coinId:string}>();


or


interface RouteParams {
	coinId:string;
}

const { coinId } = useParams<RouteParams>();

이렇게 사용하면 / 뒤에 입력된 coinId의 정보를 useParams가 잡아낸다.

react에선 요소에 링크를 걸어주기 위해 anchor 대신 <Link>를 사용한다.

<Link to="url" or {`/${주소}`}> 글자 </Link>

결국 홈페이지에서 볼 때에는 anchor로 번역이 되어 들어오게 된다.
Link요소의 css를 변경할 때 그냥 a로 하고 css를 작성해주면 된다.

const Coin = styled.li`
    color: ${(props) => props.theme.bgColor};
    &:hover {
        a{
            color: ${(props) => props.theme.accentColor};
        }
    }
`;

API 가져오기(fetch)

useState<CoinInterface[]>([]);
//<CoinInterface[]>로 배열을 가져올 것임을 알려준다.

useEffect는 내가 실행하고자 하는 함수가 실행되는 시점을 정해줄 수 있다.(한 번만 할건지 여러 번 할건지도)

원래는 useEffect 내에 함수를 직접 적지 못하지만, 할 수 있는 방법이 있다.

useEffect( () => {

(()=>{실행할 함수 코드})();   //()(); 이런 형태

}, []); // []를 넣으면 처음 한 번만 실행하겠다는 의미

복습

function Coins() {
    const [coins, setCoins] = useState<CoinInterface[]>([]);
                          // CoinInterface는 api를 배열의 interface 이름
                             배열이기 때문에 뒤에 []붙이기 (끝없이 세뇌하기,,)
    useEffect(()=> {
        (async () => { 
            const response = await fetch("url");
                                  //api 불러오기
            const json = await response.json();
            				     // 자료가 json형식이어서 json 불러오기
            setCoins(json.slice(0,100));
            					// 자료 0부터 100까지만 가져오기(그 뒤는 자르기)
        })();
    }, []);
   							 // setCoins는 coins에 자료를 넣어주는 역할
   							 setCoins()안에 넣는 자료를 coins에 넣어준다.
    
    {loading ? <Loader>Loading...</Loader> : (
           <CoinsList>
           {coins.map((coin) => <Coin key={coin.id}>
            <Link to={`/${coin.id}`}>{coin.name} &rarr;</Link>    
           </Coin>)}
       </CoinsList>
    )}
    
    // map은 배열의 index 하나하나를 정렬시켜 넣어주는 방법
    (위의 setCoins로 json정보를 받은 coins의 json 정보들을 li안에 넣어서 보여주는 코드)
    

Route States

Link는 사실 여러 가지 형태로 불러올 수 있다.
그 중 하나는 object 형태인데, Link object의 요소 중 state를 통해 api로 얻은 정보를 다른 페이지에 보내줄 수도 있다.

이걸 이용하면 api정보를 페이지마다 일일히 불러오지 않아도 된다는 이야기

useLocation

react router DOM이 state를 통해 보낸 정보(location object)에 접근하기 위해 useLocation을 사용한다.

const location = useLocation();

Coin 개별 화면에 출력할 코드

interface RouteState{
    name:string
}

function Coin() {
    const [loading, setLoading] = useState(true);
    const { coinId } = useParams<RouteParams>();
    const { state } = useLocation<RouteState>();
    return  (<Container>
    <Header>
        <Title>{state.name}</Title>
    </Header>
{loading ? <Loader>Loading...</Loader> : null
}
</Container>
)}

api에게 직접 받지 않고 state로 받은 정보들을 받아와 사용한다.

📌 이 경우, api로 먼저 정보를 받아온 후에 개별 화면으로 가야 state로 정보를 받는 것이 가능하다.(메인 홈화면 먼저 갔다가 개별 페이지로 이동해야한다는 의미이다.)

에러가 발생하기 때문에 정보가 없을 경우 Loading창 띄워주자


🚫Error🚫

optional chaining

<Title>{state?.name || "Loading..."}</Title>

?와 || 연산자를 함께 사용해 조건식을 만드는걸 optional chaining이라고 한다.(검색하다가 주워들음)

state.name을 출력하면 정보가 잘 나오는데, 왜 옵셔널 체이닝은 안되는 건지 모르겠다.

해결해보자..^^

<Title>{state.name ? state.name : "Loading..."}</Title>

이렇게 변경하니 잘 된다.
버전 탓인건지...?

📍 에러 발생 원인

이 부분 그냥 넘어가려다가 에러로 인해 다음 강의 진행이 도저히 되지 않아서 해결책을 찾아보았다.

모두 버전이나 babel을 다시 설치하라는 해결책을 내놓았는데 아무것도 통하지 않았다.

내가 아무리 리액트와 타입스크립트 버전을 변경해도 도중에 해결해본다고 이것저것 건들였던게 꼬여서 해결이 안되는 것 같았다.

결국 아예 코드 짜는 폴더를 통째로 삭제하고 처음부터 다시 시작했다.
환경 설정할 때에도 node는 그냥 패키지 째 다운받고, 리액트와 타입스크립트를 한 번에 설치해버렸다.

물론 중간에 에러가 한 번 났는데, 그건 내가 리액트를 최신 버전이 아닌 강의에 맞춘 5.3.0 버전으로 바꾸었는데 반영이 되지 않아서였고, npm 서버를 죽였다가 다시 시작하니까 잘 됐다.

그리고 아직까지 막힘없이 되는 중!

결론

해결책이라고 함부러 수정하고 삭제하고 재설치하지 말고 신중하게 해결하자.
그리고 리액트-타입스크립트 쓸거면 그냥 한 번에 설치하자...........


fetch로 불러와 저장한 coin의 데이터를 typescript에게 어떤 데이터인지설명해주는 과정이 필요하다

interface를 사용하기 전에, 데이터를 console에 불러와 console에 뜬 데이터를 마우스 우 클릭을 하게 되면 share object as global variable이라는 항목이 있다.
이걸 누르게 되면 temp1, temp2.. 라는 곳에 데이터가 저장이 된다.

이렇게 데이터를 저장해놓는 이유는 오브젝트 안의 모든 데이터의 타입을 일일히 직접 적을 필요가 없기 떄문이다.

console 창에

Object.keys(temp1) => 오브젝트 데이터의 키 값들이 나옴(name, id 등등..)
Object.values(temp1) => 오브젝트 데이터의 값들이 나옴(bitcoin 같은 :의 오른쪽값)

.join() => keys나 values로 뽑아낸 값들을 string화 해줌
.map( v => typeof v) => 배열로 이루어진 values 값들의 타입을 알려줌

이렇게 얻어낸 값들을 복사해서 붙여넣으면 직접 입력은 안해도 된다!

💚 소소한 팁 💚

interface의 이름을 지을 때, 이름 앞에 대문자 I를 써서 interface임을 알려주는 방법이 있다.

보통 사용하는 변수의 이름과 똑같이 지을 때 사용한다. (물론 인터페이스의 이름은 첫글자를 대문자로 쓰긴 하지만 I를 붙여두면 명확히 표시가 가능하다.)

Nested Route

Route 안의 route를 말한다.
웹사이트에서 탭을 사용할 때 도움이 된다.

몇 가지 요소는 항상 똑같이 나오고, 선택한 부분만 리렌더링 되길 원할 때 사용한다.

여기서는 미리 만들어둔 해당 코인의 정보들은 그대로 두되,
가격과 차트 탭을 만들어 가격과 차트만 서로 바꿀 수 있도록 하는 것이다.

Switch안에 두 개의 라우트를 만들어 일단 url에 따른 두 가지의 화면을 만든 후,
Link를 통해 화면을 바꾼다.

useRouteMatch

사용자가 특정한 URL에 있는지의 여부를 알려준다.
해당 URL에 있다면 object 정보가 나오고, 그렇지 않으면 null값이 나옴.
(그래서 isActive로 Tab 활성화 시킬때 !== null 사용)

너무 길어서 React Query는 따로 써야지

profile
응애 아직 개발아기도치

0개의 댓글