인프런 커뮤니티 질문&답변

cofla411님의 프로필 이미지
cofla411

작성한 질문수

Slack 클론 코딩[실시간 채팅 with React]

TypeError (0 , swr__WEBPACK_IMPORTED_MODULE_5__.useSWRConfig) is not a function 에러와 관련하여 질문 드립니다.

작성

·

1.3K

0

안녕하세요. 강의를 듣다가 에러가 발생하여 질문드립니다. 타입스크립트를 다루는데 익숙하지 않아 에러가 어디서 발생했는지 가늠이 잘 안됩니다ㅜㅜ

공지사항에 올려주신 대로 ser-devtools 업데이트에 맞게 client.tsx를 아래와 같이 수정했는데 다음과 같은 에러메세지가 계속 나와 화면이 보이지 않습니다 

코드를 수정할 때 core-js와 @jjordy/swr-devtools 를 함께 설치해주었습니다. 이때 @jjordy/swr-devtools 를 설치할 때 에러가 나 -f로 강제로 설치했었는데 혹시 이것이 문제가 되는 것일까요?

 

 

 

 

답변 5

0

cofla411님의 프로필 이미지
cofla411
질문자

감사합니다. 어제 user===false로 지정하자 아래 질문과 같은 에러가 발생하였습니다. 에러문은 아래와 같습니다.

const userData: IUser | undefined 개체가 'undefined'인 것 같습니다.ts(2532)

typings 설정도 제대로 했는데 왜 이런 오류가 발생하는 걸까요..? 혹시 몰라 typings 코드도 함께 남겨드립니다..

https://www.inflearn.com/questions/370629

 

export interface IUser {
id: number;
nickname: string;
email: string;
Workspaces: IWorkspace[];
}
 
export interface IUserWithOnline extends IUser {
online: boolean;
}
 
export interface IChannel {
id: number;
name: string;
private: boolean; // 비공개 채널 여부, 강좌에서는 모두 false(공개)
WorkspaceId: number;
}
 
export interface IChat {
// 채널의 채팅
id: number;
UserId: number;
User: IUser; // 보낸 사람
content: string;
createdAt: Date;
ChannelId: number;
Channel: IChannel;
}
 
export interface IDM {
// DM 채팅
id: number;
SenderId: number; // 보낸 사람 아이디
Sender: IUser;
ReceiverId: number; // 받는 사람 아이디
Receiver: IUser;
content: string;
createdAt: Date;
}
 
export interface IWorkspace {
id: number;
name: string;
url: string; // 주소 창에 보이는 주소
OwnerId: number; // 워크스페이스 만든 사람 아이디
}

 

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

IUser | false를 IUser | false | undefined 로 바꿔보세요

0

cofla411님의 프로필 이미지
cofla411
질문자

아래 페이지로 이동합니다 ..! 

 

https://support.google.com/chrome/answer/95669?visit_id=637797567181515999-2649936511&p=e_awsnap&rd=1

 

 

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

if (!userData)를 if (userData === false) 로 바꿔보세요.

0

cofla411님의 프로필 이미지
cofla411
질문자

/workspace/:workspace로 바꾼 이후에도 http://localhost:3090/workspace/channel로 이동이 되지 않습니다.. 

위 사진과 같이 네트워크 창에 channel이 생기지 않습니다. login에서 workspace/channel로 넘어가는데 문제가 있는 것 같은데 대체 어디서 문제가 발생하는 것인지 모르겠습니다..

나중에 로딩에 실패하고 다시 새로고침을 하면 아래와 같이 channel이 네트워크에서 보입니다. 

  1. Request URL:
    http://localhost:3090/workspace/channel

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

저기서 자세히 알아보기 누르면 뭐가 뜨나요?

0

cofla411님의 프로필 이미지
cofla411
질문자

답변 감사드립니다. package.json에서 확인해본 결과 아래와 같습니다!

 
"@jjordy/swr-devtools": "^2.2.0",
"swr": "^0.4.2",
 
제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

swr 1버전이 아니시네요. 그럼 강좌 영상에 나온대로 쓰셔야 합니다. @jjordy/swr-devtools도 1버전을 설치하셔야 하고요. npm i @jjordy/swr-devtools@1

cofla411님의 프로필 이미지
cofla411
질문자

감사합니다! 이부분은 해결했습니다. 다만 swr에러를 해결하고 나니 map관련 오류가 발생하여 아래 부분을 다음과 같이 수정하니 로그인에서 http://localhost:3090/workspace/channel로 넘어가는 화면이 뜨지 않습니다.. 어느 부분을 수정해야하는 걸까요..? 혹시 db쪽에 문제가 있는 것일까요?

{userData?.Workspaces?.map((ws)=>{

다음은 Workspace의 index.tsx 코드입니다

import {
AddButton,
Channels,
Chats,
Header,
LogOutButton,
MenuScroll,
ProfileImg,
ProfileModal,
RightMenu,
WorkspaceButton,
WorkspaceModal,
WorkspaceName,
Workspaces,
WorkspaceWrapper,
} from './styles';
import React, { FC, useCallback, useState } from "react";
import fetcher from "@utils/fetcher";
import useSWR from "swr";
import axios from "axios";
import{Link, Redirect, Route, Switch} from "react-router-dom";
import gravatar from 'gravatar';
import loadable from "@loadable/component";
import Menu from "@components/Menu";
import { IUser } from "@typings/db";
import { Button, Input, Label } from "@pages/SignUp/styles";
import useInput from "@hooks/useInput";
import Modal from '@components/Modal';


const Channel=loadable(()=>import('@pages/Channel'));
const DirectMessage=loadable(()=>import('@pages/DirectMessage'));

const Workspace: FC=({children})=>{
const [newUrl, onChangeNewUrl, setNewUrl]=useInput('');
const [newWorkspace, onChangeNewWorkspace, setNewWorkspace]=useInput('');
const [showUserMenu, setShowUserMenu]=useState(false);
const [showCreateWorkspaceModal, setShowCreateWorkspaceModal]=useState(false);
const { data:userData, error, revalidate, mutate } = useSWR<IUser | false>('http://localhost:3095/api/users', fetcher, {
dedupingInterval: 2000, //2초
});

const onLogout=useCallback(()=>{
axios
.post('http://localhost:3095/api/users/logout',null, {
withCredentials: true,
} )
.then(()=>{
mutate(false, false);
})
}, []);

const onCloseUserProfile=useCallback((e)=>{
e.stopPropagation();
setShowUserMenu(false);
}, []);

const onClickUserProfile=useCallback(()=>{
setShowUserMenu((prev)=>(!prev));
}, []);

const onClickCreateWorkspace=useCallback(()=>{
setShowCreateWorkspaceModal(true);
}, []);

const onCreateWorkspace=useCallback(()=>{

}, []);

const onCloseModal=useCallback(()=>{
setShowCreateWorkspaceModal(false);
}, []);

if(!userData){ //로그아웃해서 data가 false가 되는 순간 login페이지로 보내버림
return <Redirect to="/login"/>;
}

return(
<div>
<Header>
<RightMenu>
<span onClick={onClickUserProfile}>
<ProfileImg src={gravatar.url(userData.email, {s: '28px', d: 'retro'})} alt={userData.nickname}/>
{showUserMenu && (
<Menu style={{right: 0, top: 38}} show={showUserMenu} onCloseModal={onClickUserProfile}>
<ProfileModal>
<img src={gravatar.url(userData.email, {s: '36px', d: 'retro'})} alt={userData.nickname}/>
<div>
<span id="profile-name">{userData.nickname}</span>
<span id="profile-active">Active</span>
</div>
</ProfileModal>
<LogOutButton onClick={onLogout}>로그아웃</LogOutButton>
</Menu>
)}
</span>
</RightMenu>
 
</Header>
<button onClick={onLogout}>로그아웃</button>
<WorkspaceWrapper>
<Workspace>
{userData?.Workspaces?.map((ws)=>{
return(
<Link key={ws.id} to={'/workspace/${}/channel/일반'}>
<WorkspaceButton>{ws.name.slice(0, 1).toUpperCase()}</WorkspaceButton>
</Link>
)
})}
<AddButton>onClick={onClickCreateWorkspace}</AddButton>
</Workspace>
<Channels>
<WorkspaceName>Sleact</WorkspaceName>
<MenuScroll>menu scroll</MenuScroll>
</Channels>
<Chats>
<Switch>
<Route path="/workspace/channel" component={Channel}/>
<Route path="/workspace/dm" component={DirectMessage}/>
</Switch>
</Chats>
</WorkspaceWrapper>
<Modal show={showCreateWorkspaceModal} onCloseModal={onCloseModal}>
<form onSubmit={onCreateWorkspace}>
<Label id='workspace-label'>
<span>워크스페이스 이름</span>
<Input id='workspace' value={newWorkspace} onChange={onChangeNewWorkspace}/>
</Label>
<Label id='workspace-url-label'>
<span>워크스페이스 이름</span>
<Input id='workspace' value={newUrl} onChange={onChangeNewUrl}/>
</Label>
<Button type="submit">생성하기</Button>
</form>
</Modal>
{children}
</div>
)
}

export default Workspace;
 
cofla411님의 프로필 이미지
cofla411
질문자

추가로 마지막에 다음과 같은 에러메세지가 나오고 결국 workspace/channel이 로딩되지 않습니다. 

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

저건 에러가 아니고요. layouts/App 보여주세요.

cofla411님의 프로필 이미지
cofla411
질문자

네 감사합니다 ! App/index.tsx입니다. 

 

import React from "react";
import loadable from "@loadable/component";
import {Switch, Route, Redirect} from 'react-router-dom';


const LogIn =loadable(()=> import('@pages/LogIn'));
const SignUp =loadable(()=> import( '@pages/SignUp'));
const Workspace=loadable(()=>import('@layouts/Workspace'));

const App=()=>{

return (
<Switch> //세개 중에 하나의 컴포넌트만 보이게 됨.
<Redirect exact path="/" to="/login"/>
<Route path="/login" component={LogIn} />
<Route path="/signup" component={SignUp} />
<Route path="/workspace" component={Workspace}/>
</Switch>
);
};

export default App;
제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

주소를 /workspace/:workspace로 바꿔보세요

cofla411님의 프로필 이미지
cofla411
질문자

package.json에서 확인해본 결과 리액트라우터5 사용중인 것 같습니다..!

"react-router": "^5.2.1",
"react-router-dom": "^5.3.0",

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

swr이랑 swr-devtools 버전 알려주세요.

cofla411님의 프로필 이미지
cofla411

작성한 질문수

질문하기