해결된 질문
작성
·
198
1
1. 로그인을 성공하면, 회원에 대한 정보도 정상적으로 가져오고 화면은 정상적으로 나오지만,
useSWR을 통해 체널 데이터를 못가져오는 것 같습니다.
2. 채널 만들기를 하면 500 에러가 발생합니다.
query: SELECT DISTINCT `distinctAlias`.`Users_id` AS `ids_Users_id` FROM (SELECT `Users`.`id` AS `Users_id`, `Users`.`email` AS `Users_email`, `Users`.`nickname` AS `U
sers_nickname`, `Users__Users_Workspaces`.`id` AS `Users__Users_Workspaces_id`, `Users__Users_Workspaces`.`name` AS `Users__Users_Workspaces_name`, `Users__Users_Works
paces`.`url` AS `Users__Users_Workspaces_url`, `Users__Users_Workspaces`.`createdAt` AS `Users__Users_Workspaces_createdAt`, `Users__Users_Workspaces`.`updatedAt` AS `
Users__Users_Workspaces_updatedAt`, `Users__Users_Workspaces`.`deletedAt` AS `Users__Users_Workspaces_deletedAt`, `Users__Users_Workspaces`.`OwnerId` AS `Users__Users_
Workspaces_OwnerId` FROM `users` `Users` LEFT JOIN `workspacemembers` `Users_Users__Users_Workspaces` ON `Users_Users__Users_Workspaces`.`UserId`=`Users`.`id` LEFT JOI
N `workspaces` `Users__Users_Workspaces` ON `Users__Users_Workspaces`.`id`=`Users_Users__Users_Workspaces`.`WorkspaceId` AND (`Users__Users_Workspaces`.`deletedAt` IS
NULL) WHERE ( (`Users`.`id` = ?) ) AND ( `Users`.`deletedAt` IS NULL )) `distinctAlias` ORDER BY `Users_id` ASC LIMIT 1 -- PARAMETERS: [5]
query: SELECT `Users`.`id` AS `Users_id`, `Users`.`email` AS `Users_email`, `Users`.`nickname` AS `Users_nickname`, `Users__Users_Workspaces`.`id` AS `Users__Users_Wor
kspaces_id`, `Users__Users_Workspaces`.`name` AS `Users__Users_Workspaces_name`, `Users__Users_Workspaces`.`url` AS `Users__Users_Workspaces_url`, `Users__Users_Worksp
aces`.`createdAt` AS `Users__Users_Workspaces_createdAt`, `Users__Users_Workspaces`.`updatedAt` AS `Users__Users_Workspaces_updatedAt`, `Users__Users_Workspaces`.`dele
tedAt` AS `Users__Users_Workspaces_deletedAt`, `Users__Users_Workspaces`.`OwnerId` AS `Users__Users_Workspaces_OwnerId` FROM `users` `Users` LEFT JOIN `workspacemember
s` `Users_Users__Users_Workspaces` ON `Users_Users__Users_Workspaces`.`UserId`=`Users`.`id` LEFT JOIN `workspaces` `Users__Users_Workspaces` ON `Users__Users_Workspace
s`.`id`=`Users_Users__Users_Workspaces`.`WorkspaceId` AND (`Users__Users_Workspaces`.`deletedAt` IS NULL) WHERE ( (`Users`.`id` = ?) ) AND ( `Users`.`deletedAt` IS NUL
L ) AND ( `Users`.`id` IN (5) ) -- PARAMETERS: [5]
user Users {
id: 5,
email: 'qqq123@naver.com',
nickname: 'Quit',
Workspaces: [
Workspaces {
id: 1,
name: 'Sleact',
url: 'select',
createdAt: 2022-08-20T04:04:09.828Z,
updatedAt: 2022-08-20T04:04:09.828Z,
deletedAt: null,
OwnerId: null
}
]
}
query: SELECT `Workspaces`.`id` AS `Workspaces_id`, `Workspaces`.`name` AS `Workspaces_name`, `Workspaces`.`url` AS `Workspaces_url`, `Workspaces`.`createdAt` AS `Work
spaces_createdAt`, `Workspaces`.`updatedAt` AS `Workspaces_updatedAt`, `Workspaces`.`deletedAt` AS `Workspaces_deletedAt`, `Workspaces`.`OwnerId` AS `Workspaces_OwnerI
d` FROM `workspaces` `Workspaces` WHERE ( (`Workspaces`.`url` = ?) ) AND ( `Workspaces`.`deletedAt` IS NULL ) LIMIT 1 -- PARAMETERS: ["sleact"]
[Nest] 19948 - 2022. 08. 20. 오후 1:33:12 ERROR [ExceptionsHandler] Cannot read properties of null (reading 'id')
TypeError: Cannot read properties of null (reading 'id')
at ChannelsService.createWorkspaceChannels (C:\Users\kwa13\IdeaProjects\sleact\back\dist\main.js:2034:41)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async C:\Users\kwa13\IdeaProjects\sleact\back\node_modules\@nestjs\core\router\router-execution-context.js:46:28
at async C:\Users\kwa13\IdeaProjects\sleact\back\node_modules\@nestjs\core\router\router-proxy.js:9:17
[Nest] 19948 - 2022. 08. 20. 오후 1:33:12 LOG [HTTP] POST /api/workspaces/sleact/channels 500 52 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (K
HTML, like Gecko) Chrome/104.0.0.0 Safari/537.36 ::ffff:127.0.0.1
------------------------------------------------------------------------------------------------------------------------
DB 관련 스크린샷
- 채널
- 워크스페이스
-------------------------------------------------------------------------------------------
백엔드 관련 코드
- channels.controller.ts
@Controller('api/workspaces/:url/channels')
export class ChannelsController {
constructor(private readonly channelsService: ChannelsService) {}
@ApiOperation({ summary: '채널 생성하기' })
@Post()
async createChannel(
@Param('url') url: string,
@Body() body: CreateChannelDto,
@User() user: Users,
) {
return this.channelsService.createWorkspaceChannels(
url,
body.name,
user.id,
);
}
- channels.service.ts
async getWorkspaceChannels(url: string, myId: number) {
return this.channelsRepository
.createQueryBuilder('channels')
.innerJoinAndSelect(
'channels.ChannelMembers',
'channelMembers',
'channelMembers.userId = :myId',
{ myId },
)
.innerJoinAndSelect(
'channels.Workspace',
'workspace',
'workspace.url = :url',
{ url },
)
.getMany();
}
-----------------------------------------------------------------------------------------------------------------------
프론트엔드 관련 코드
- Workspace/index.tsx
const Workspace = () => {
const [showUserMenu, setShowUserMenu] = useState(false);
const [showCreateWorkspaceModal, setShowCreateWorkspaceModal] = useState(false);
const [showWorkspaceModal, setShowWorkspaceModal] = useState(false);
const [showCreateChannelModal, setShowCreateChannelModal] = useState(false);
const [newWorkspace, onChangeNewWorkspace, setNewWorkspace] = useInput('');
const [newUrl, onChangeNewUrl, setNewUrl] = useInput('');
const { workspace } = useParams();
const { data: userData, error, mutate } = useSWR<IUser | false>('/api/users', fetcher);
const { data: channelData } = useSWR<IChannel[]>(userData ? `/api/workspaces/${workspace}/channels` : null, fetcher);
const onLogout = useCallback(() => {
axios
.post('/api/users/logout', null, {
withCredentials: true,
})
.then(() => {
mutate();
});
}, []);
const onClickUserProfile = useCallback(() => {
setShowUserMenu((prev) => !prev);
}, []);
const onCloseUserProfile = useCallback((e: any) => {
e.stopPropagation();
setShowUserMenu(false);
}, []);
const onClickCreateWorkspace = useCallback(() => {
setShowCreateWorkspaceModal(true);
}, []);
const onCloseModal = useCallback(() => {
setShowCreateWorkspaceModal(false);
setShowCreateChannelModal(false);
}, []);
const onCreateWorkspace = useCallback(
(e: any) => {
e.preventDefault();
if (!newWorkspace || !newWorkspace.trim()) return;
if (!newUrl || !newUrl.trim()) return;
axios
.post(
'/api/workspaces',
{
name: 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 toggleWorkspaceModal = useCallback(() => {
setShowWorkspaceModal((prev) => !prev);
}, []);
const onClickAddChannel = useCallback(() => {
setShowCreateChannelModal(true);
}, []);
if (!userData) {
return <Navigate replace 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={onCloseUserProfile}>
<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>
<WorkspaceWrapper>
<Workspaces>
{userData?.Workspaces.map((ws) => {
return (
<Link key={ws.id} to={`/workspace/sleact/channel/일반`}>
<WorkspaceButton>{ws.name.slice(0, 1).toUpperCase()}</WorkspaceButton>
</Link>
);
})}
<AddButton onClick={onClickCreateWorkspace}>+</AddButton>;
</Workspaces>
<Channels>
<WorkspaceName onClick={toggleWorkspaceModal}>WorkspaceName</WorkspaceName>
<MenuScroll>
<Menu show={showWorkspaceModal} onCloseModal={toggleWorkspaceModal} style={{ top: 95, left: 80 }}>
<WorkspaceModal>
<h2>Sleact</h2>
<button onClick={onClickAddChannel}>채널 만들기</button>
<button onClick={onLogout}>로그아웃</button>
</WorkspaceModal>
</Menu>
{channelData?.map((v) => (
<div>{v.name}</div>
))}
</MenuScroll>
</Channels>
<Chats>
<Routes>
<Route path="/channel/:channel" element={<Channel />} />
<Route path="/dm/:id" element={<DM />} />
</Routes>
</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>워크스페이스 url</span>
<Input id="workspace" value={newUrl} onChange={onChangeNewUrl} />
</Label>
<Button type="submit">생성하기</Button>
</form>
</Modal>
<CreateChannelModal
show={showCreateChannelModal}
onCloseModal={onCloseModal}
setShowCreateChannelModal={setShowCreateChannelModal}
/>
</div>
);
};
export default Workspace;
- CreateChannelModal/index.tsx
interface Props {
show: boolean;
onCloseModal: () => void;
setShowCreateChannelModal: (flag: boolean) => void;
}
const CreateChannelModal: VFC<Props> = ({ show, onCloseModal, setShowCreateChannelModal }) => {
const [newChannel, onChangeNewChannel, setNewChannel] = useInput('');
const { workspace, channel } = useParams();
const onCreateChannel = useCallback(
(e: any) => {
e.preventDefault();
axios
.post(
`/api/workspaces/${workspace}/channels`,
{
name: newChannel,
},
{ withCredentials: true },
)
.then(() => {
setShowCreateChannelModal(false);
setNewChannel('');
})
.catch((error) => {
console.dir(error);
toast.error(error.response?.data, { position: 'bottom-center' });
});
},
[newChannel],
);
return (
<Modal show={show} onCloseModal={onCloseModal}>
<form onSubmit={onCreateChannel}>
<Label id="channel-label">
<span>채널</span>
<Input id="channel" value={newChannel} onChange={onChangeNewChannel} />
</Label>
<Button type="submit">생성하기</Button>
</form>
</Modal>
);
};
export default CreateChannelModal;
스스로 해결해보려고 많은 시간을 들여봤지만, 도저히 모르겠네요..
답변 1
0
ChannelsService.createWorkspaceChannels (C:\Users\kwa13\IdeaProjects\sleact\back\dist\main.js:2034:41
여기에 에러가 있다고 나와있는데 여기 확인해보셨나요?
x.id에서 x가 null이니 x가 뭔지 확인하셔야합니다.
감사합니다! 그 부분 찾아보니까 workspace였고, 관련 코드 가보니 아무리봐도 틀린 부분이 없어서 DB 부분 가보니까... url에 sleact가 아니라 select로 저장해놨더군요.!
sleact으로 바꾸니까 잘작동합니다. 감사합니다 좋은 주말보내세요.