작성
·
1.7K
0
제로초님, 코드를 따라친 후에 로그아웃을 하고 다시 로그인 하면 이런 에러메세지가 뜹니다.
그런데 네트워크 탭을 보면 로그인이 정상적으로 된거 같아서 새로고침을 하면 에러 메세지가 사라지고 슬랙에서 로그인된 화면이 제대로 뜹니다.
근데 또 여기서 워크스페이스를 생성하려고 하면 콘솔에 axioserror메세지가 떠서 어떻게 해야될지 모르겠습니다..
Workspace/index.tsx
import axios from "axios";
import React, { FC, useCallback, useState } from "react";
import useSWR from 'swr';
import fetcher from "@utils/fetcher";
import { Navigate, Routes, Route } from "react-router-dom";
import { AddButton, Channels, Chats, Header, LogOutButton, MenuScroll, ProfileImg, ProfileModal, RightMenu, WorkspaceButton, WorkspaceName, Workspaces, WorkspaceWrapper } from "@layouts/Workspace/style";
import gravatar from 'gravatar';
import loadable from '@loadable/component';
import Menu from "../../components/Menu";
import Modal from "../../components/Modal";
import { Link } from "react-router-dom";
import { IUser } from "@typings/db";
import { Button, Input, Label } from "@pages/SignUp/styles";
import useInput from "@hooks/useInput";
import {toast} from 'react-toastify';
const Channel = loadable(() => import('@pages/Channel'));
const DirectMessage = loadable(() => import('@pages/DirectMessage'));
const Workspace: FC<React.PropsWithChildren<{}>> = ({children}) => {
const [showUserMenu, setShowUserMenu] = useState(false);
const [showCreateWorkspaceModal, setShowCreateWorkspaceModal] = useState(false);
const [newWorkspace, onChangeNewWorkspace, setNewWorkspace] = useInput('');
const [newUrl, onChangeNewUrl, setNewUrl] = useInput('');
// revalidate = 서버로 요청 다시 보내서 데이터를 다시 가져옴
// mutate = 서버에 요청 안보내고 데이터를 수정
const {data: userData, error, mutate} = useSWR<IUser | false>('/api/users', fetcher, {
dedupingInterval: 2000,
});
const onLogout = useCallback(() => {
axios.post('/api/users/logout', null , {
withCredentials: true,
})
.then(() => {
mutate(false, false);
})
}, []);
const onClickUserProfile = useCallback((e: any) => {
e.stopPropagation();
setShowUserMenu((prev) => !prev);
}, [])
const onClickCreateWorkspace = useCallback(() => {
setShowCreateWorkspaceModal(true);
}, [])
const onCreateWorkspace = useCallback((e: any) => {
e.preventDefault();
// 띄어쓰기도 검사해줘야됨
if(!newWorkspace || !newWorkspace.trim()) return;
if(!newUrl || !newUrl.trim()) return;
axios.post('http://localhost:3095/api/workspaces', {
workspace: newWorkspace,
url: newUrl,
}, {
withCredentials: true,
})
.then(() => {
mutate();
setShowCreateWorkspaceModal(false);
setNewWorkspace('');
setNewUrl('');
})
.catch((error) => {
console.dir(error);
// 에러가 나면 사용자가 인지하게 해줌
toast.error(error.response?.data, { position: 'bottom-center' })
})
}, [newWorkspace, newUrl])
const onCloseModal = useCallback(() => {
setShowCreateWorkspaceModal(false);
}, [])
if(!userData) {
return <Navigate to="/login" />
}
if(!userData) return null;
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.nickname, { 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>
<WorkspaceWrapper>
<Workspaces>
{userData?.Workspaces.map((ws) => {
return (
<Link key={ws.id} to={`/workspace/${123}/channel/일반`}>
<WorkspaceButton>{ws.name.slice(0, 1).toUpperCase()}</WorkspaceButton>
</Link>
);
})}
<AddButton onClick={onClickCreateWorkspace}>+</AddButton>
</Workspaces>
<Channels>
<WorkspaceName>Sleact</WorkspaceName>
<MenuScroll>menu scroll</MenuScroll>
</Channels>
<Chats>
<Routes>
<Route path="/channel" element={<Channel />} />
<Route path="/dm" element={<DirectMessage />} />
</Routes>
</Chats>
{/* Input이 들어있으면 별도의 컴포넌트로 빼는 것을 추천(input에 글자를 입력할 때마다 여기 있는 함수들이 다 리렌더링 되기 때문에 비효율적) */}
</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>
</div>
)
}
export default Workspace;
Modal/index.tsx
import React, { useCallback, FC } from "react";
import { CloseModalButton, CreateModal } from "./style";
interface Props {
show: boolean;
onCloseModal: () => void;
children: React.ReactNode;
}
const Modal: FC<Props> = ({show, children, onCloseModal}) => {
const stopPropagation = useCallback((e: any) => {
e.stopPropagation()
}, []);
if(!show){
return null;
}
return(
<CreateModal onClick={onCloseModal}>
<div onClick={stopPropagation}>
<CloseModalButton onClick={onCloseModal}>×</CloseModalButton>
{children}
</div>
</CreateModal>
);
};
export default Modal;
swr2.0 버전, react v18, typescript v18
swr을 최신버전 사용해서 revalidate대신 mutate를 사용했는데 제가 잘못 사용한건지 모르겠습니다.
답변 2
0
userData.Workspaces가 undefined인데 map이 돼서 오류가 난거 같아서 코드를
<Workspaces>
{userData.Workspaces !== undefined
?userData?.Workspaces.map((ws) => {
return (
<Link key={ws.id} to={`/workspace/${123}/channel`}>
<WorkspaceButton>{ws.name.slice(0, 1).toUpperCase()}</WorkspaceButton>
</Link>
)
})
: null
}
<AddButton onClick={onClickCreateWorkspace}>+</AddButton>
</Workspaces>
이렇게 변경하니까 에러가 해결되네요
조언해주셔서 감사합니다!
0
네트워크탭에서 빨간색이 있으면 그걸 누르고 헤더를 먼저 보여주세요. 그게 에러 해결의 실마리입니다.
그리고 network error로 되어있으므로 서버 에러 메시지도 보여주세요.
헤더탭 왼쪽에 있는 x를 눌러서 네트워크탭을 보여주세요. 지금 에러메시지가 뭔가 가려져있어서 문제 파악이 안 됩니다. 콘솔에 빨간에러 6개와 추가로 1개가 더 있는데 전부 알아야 합니다.
그리고 api 요청시 3095로 하시는 이유가 있나요? proxy 서버를 사용하세요.
그 마지막 영상 부분에 api 요청을 3095로 바꿔서 그대로 똑같이 바꿨습니다!
말씀해주신대로 proxy서버로 바꿔서 사용했는데 워크스페이스를 생성하면 처음에는 성공하는데 그 후부터는 성공하지 않습니다.
workspace 생성 성공했을 때
workspace 실패했을 때
네트워크 탭입니다
콘솔 에러메세지입니다
오 일단 워크스페이스까지는 다 됐습니다 감사합니다!!
근데 로그인 할 때 에러메세지는 왜 뜨는 건가요?
저 상태에서 새로고침하면 로그인된 화면으로 전환되는데 오류가 아닌건가요?
userData?.Workspaces?.map 만 해도 됩니다