묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Slack 클론 코딩[실시간 채팅 with React]
오류 문의
강의를 따라하는 도중에 npx sequelize db:create를 입력하였을때는 정상적으로 "Database sleact create."라는 메세지가 확인됬습니다. 그 이후로 yarn dev를 실행하니 아래와 같은 오류가 확인됬습니다.이유가 뭘까요?ㅜㅜ
-
미해결프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
폴더를 prettier로 돌렸을 때 나오는 에러 구문에 대한 질문
npx prettier ./src --write해당 구문이 적용되나요? 첫 시도에서는 성공했는데 그 이후로 부터는 실패 구문이 아래와 같이 뜨더라구요.[error] No matching files. Patterns tried: ./src !**/node_modules/** !./node_modules/** !**/.{git,svn,hg}/** !./.{git,svn,hg}/**안내 답변 가능하신가요?
-
미해결Slack 클론 코딩[실시간 채팅 with React]
Direct Messages에 값이 없어요
안녕하세요.import React from 'react'; import { Container, Header } from './styles'; import useSWR from 'swr'; import fetcher from '@utils/fetcher'; import { useParams } from 'react-router'; import gravatar from 'gravatar'; const DirectMessage = () => { const { workspace, id } = useParams<{ workspace: string; id: string }>(); const { data: userData } = useSWR(`api/workspaces/${workspace}/members/${id}`, fetcher); const { data: myData } = useSWR('api/users', fetcher); if (!userData || !myData) { return null; } return ( <Container> <Header> <img src={gravatar.url(userData.email, { s: '24px', d: 'retor' })} alt={userData.nickname} /> <span>{userData.nickname}</span> </Header> {/* <ChatList /> <ChatBox /> */} </Container> ); }; export default DirectMessage; 이건 DirectMessage입니다.// import EachDM from '@components/EachDM'; // import useSocket from '@hooks/useSocket'; import { CollapseButton } from '@components/DMList/styles'; import { IDM, IUser, IUserWithOnline } from '@typings/db'; import fetcher from '@utils/fetcher'; import React, { FC, useCallback, useEffect, useState } from 'react'; import { useParams } from 'react-router'; import { NavLink } from 'react-router-dom'; import useSWR from 'swr'; const DMList: FC = () => { const { workspace } = useParams<{ workspace?: string }>(); const { data: userData } = useSWR<IUser>('/api/users', fetcher, { dedupingInterval: 2000, // 2초 }); const { data: memberData } = useSWR<IUserWithOnline[]>( userData ? `/api/workspaces/${workspace}/members` : null, fetcher, ); // const [socket] = useSocket(workspace); const [channelCollapse, setChannelCollapse] = useState(false); const [countList, setCountList] = useState<{ [key: string]: number }>({}); const [onlineList, setOnlineList] = useState<number[]>([]); const toggleChannelCollapse = useCallback(() => { setChannelCollapse((prev) => !prev); }, []); const resetCount = useCallback( (id) => () => { setCountList((list) => { return { ...list, [id]: 0, }; }); }, [], ); const onMessage = (data: IDM) => { console.log('dm왔다', data); setCountList((list) => { return { ...list, [data.SenderId]: list[data.SenderId] ? list[data.SenderId] + 1 : 1, }; }); }; useEffect(() => { console.log('DMList: workspace 바꼈다', workspace); setOnlineList([]); setCountList({}); }, [workspace]); // useEffect(() => { // socket?.on('onlineList', (data: number[]) => { // setOnlineList(data); // }); // console.log('socket on dm', socket?.hasListeners('dm'), socket); // return () => { // console.log('socket off dm', socket?.hasListeners('dm')); // socket?.off('onlineList'); // }; // }, [socket]); return ( <> <h2> <CollapseButton collapse={channelCollapse} onClick={toggleChannelCollapse}> <i className="c-icon p-channel_sidebar__section_heading_expand p-channel_sidebar__section_heading_expand--show_more_feature c-icon--caret-right c-icon--inherit c-icon--inline" data-qa="channel-section-collapse" aria-hidden="true" /> </CollapseButton> <span>Direct Messages</span> </h2> <div> {!channelCollapse && memberData?.map((member) => { const isOnline = onlineList.includes(member.id); const count = countList[member.id] || 0; <NavLink key={member.id} activeClassName="selected" to={`/workapce/${workspace}/dm/${member.id}`} onClick={resetCount(member.id)} > ; <i className={`c-icon p-channel_sidebar__presence_icon p-channel_sidebar__presence_icon--dim_enabled c-presence ${ isOnline ? 'c-presence--active c-icon--presence-online' : 'c-icon--presence-offline' }`} aria-hidden="true" data-qa="presence_indicator" data-qa-presence-self="false" data-qa-presence-active="false" data-qa-presence-dnd="false" /> ;<span className={count > 0 ? 'bold' : undefined}>{member.nickname}</span> {member.id === userData?.id && <span> (나)</span>} {count > 0 && <span className="count">{count}</span>} </NavLink>; // return <EachDM key={member.id} member={member} isOnline={isOnline} />; })} </div> </> ); }; export default DMList; 이건 DMList입니다. 현재 DM페이지 만들기 강의를 듣고 있는데, DM리스트에 사용자가 하나도 표시가 되지 않는데 원래 지금 강의까지는 표시가 되지 않는게 맞나요? 워크스페이스 초대, 채널 멤버 초대해도 에러는 발생하지 않는데 DM리스트에 추가는 다음 강의에서 진행하나요? 아니면 지금도 되야하는게 정상인가요..?
-
미해결Slack 클론 코딩[실시간 채팅 with React]
사용자 초대 모달에서 에러가 발생했습니다.
import fetcher from '@utils/fetcher'; import axios from 'axios'; import React, { VFC, useCallback, useState } from 'react'; import { Redirect, Route, Switch, useParams } from 'react-router'; import useSWR from 'swr'; import { Header, ProfileImg, RightMenu, WorkspaceWrapper, WorkspaceName, Workspaces, Channels, Chats, MenuScroll, ProfileModal, LogOutButton, WorkspaceButton, AddButton, WorkspaceModal, } from './styles'; import gravatar from 'gravatar'; import loadable from '@loadable/component'; import Menu from '@components/Menu'; const Channel = loadable(() => import('@pages/Channel')); const DirectMessage = loadable(() => import('@pages/DirectMessage')); import { Link } from 'react-router-dom'; import { IChannel, IUser } from '@typings/db'; import Modal from '@components/Modal'; import { Button, Input, Label } from '@pages/SignUp/styles'; import useInput from '@hooks/useInput'; import { toast } from 'react-toastify'; import CreateChannelModal from '@components/CreateChannelModal'; import InviteWorkspaceModal from '@components/InviteWorkspaceModal'; import InviteChannelModal from '@components/InviteChannelModal'; // import ChannelList from '@components/ChannelList'; import DMList from '@components/DMList'; import ChannelList from '@components/ChannelList'; // FC타입안에 children이 알아서 들어있음 // children 안쓸거면 VFC const Workspace: VFC = () => { const [showUserMenu, setShowUserMenu] = useState(false); const [showCreateWorkspaceModal, setShowCreateWorkspaceModal] = useState(false); const [showInviteWorkspaceModal, setShowInviteWorkspaceModal] = useState(false); const [showInviteChannelModal, setShowInviteChannelModal] = useState(false); const [newWorkspace, onChangeNewWorkspace, setNewWorkspace] = useInput(''); const [newUrl, onChangeNewUrl, setNewUrl] = useInput(''); const [showWorkspaceModal, setShowWorkspaceModal] = useState(false); const [ShowCreateChannelModal, setShowCreateChannelModal] = useState(false); const { workspace } = useParams<{ workspace: string }>(); // 사용자 데이터 가져오기 const { data: userData, error, revalidate, mutate, } = useSWR<IUser | false>('/api/users', fetcher, { dedupingInterval: 2000, }); // channel 데이터 가져오기 const { data: channelData } = useSWR<IChannel[]>(userData ? `/api/workspaces/${workspace}/channels` : null, fetcher); // 워크스페이스에 있는 멤버 데이터 const { mutate: revalidateMembers } = useSWR<IUser[]>( userData ? `/api/workspaces/${workspace}/members` : null, fetcher, ); // 로그아웃 const onLogout = useCallback(() => { axios .post('/api/users/logout', null, { withCredentials: true, }) .then((response) => { mutate(response.data); // 기존에 받은 데이터를 mutate의 data에 담음 }) .catch((error) => { console.log(error); }); }, []); // 프로필 누르면 메뉴 보이기 const onClickUserProfile = useCallback(() => { setShowUserMenu((prev) => !prev); }, []); // 프로필 닫기 const onCloseUserProfile = useCallback((e) => { e.stopPropagation(); setShowUserMenu(false); }, []); // 워크스페이스 모달 열기 const onClickCreateWorkspace = useCallback(() => { setShowCreateWorkspaceModal(true); }, []); // 워크스페이스 모달 닫기 const onCloseModal = useCallback(() => { setShowCreateWorkspaceModal(false); setShowCreateChannelModal(false); setShowInviteChannelModal(false); setShowInviteWorkspaceModal(false); }, []); // 워크스페이스 생성 const onCreateWorkspace = useCallback( (e) => { e.preventDefault(); // trim() 안넣으면 띄어쓰기 넣으면 걍 통과됨 if (!newWorkspace || !newWorkspace.trim()) return; if (!newUrl || !newUrl.trim()) return; axios .post( '/api/workspaces', { workspace: newWorkspace, url: newUrl, }, { withCredentials: true, }, ) .then(() => { revalidate(); setShowCreateWorkspaceModal(false); setNewWorkspace(''); setNewUrl(''); }) .catch((error) => { console.log(error); toast.error(error.response?.data, { position: 'bottom-center' }); }); }, [newWorkspace, newUrl], ); // 워크스페이스 사용자 초대 const onClickInviteWorkspace = useCallback(() => { setShowInviteWorkspaceModal(true); }, []); // Channel // 토글 const toggleWorkspaceModal = useCallback(() => { setShowWorkspaceModal((prev) => !prev); }, []); // 채널 만들기 const onClickAddChannel = useCallback(() => { setShowCreateChannelModal(true); }, []); if (!userData) { return <Redirect to="/login" />; } return ( <div> <Header> <RightMenu> <span onClick={onClickUserProfile}> <ProfileImg src={gravatar.url(userData.nickname, { s: '28px', d: 'retro' })} alt={userData.nickname} /> {showUserMenu && ( <Menu style={{ right: 0, top: 38 }} show={showUserMenu} onCloseModal={onCloseUserProfile}> <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 onClick={toggleWorkspaceModal}>Sleact</WorkspaceName> <MenuScroll> <Menu show={showWorkspaceModal} onCloseModal={toggleWorkspaceModal} style={{ top: 95, left: 80 }}> <WorkspaceModal> <h2>Sleact</h2> <button onClick={onClickInviteWorkspace}>워크스페이스에 사용자 초대</button> <button onClick={onClickAddChannel}>채널 만들기</button> <button onClick={onLogout}>로그아웃</button> </WorkspaceModal> </Menu> <ChannelList /> <DMList /> {/* {channelData?.map((v) => ( <div>{v.name}</div> ))} */} </MenuScroll> </Channels> <Chats> <Switch> <Route path="/workspace/:workspace/channel/:channel" component={Channel} /> <Route path="/workspace/:workspace/dm/:id" 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>워크스페이스 url</span> <Input id="workspace" value={newUrl} onChange={onChangeNewUrl} /> </Label> <Button type="submit">생성하기</Button> </form> </Modal> <CreateChannelModal show={ShowCreateChannelModal} onCloseModal={onCloseModal} setShowCreateChannelModal={setShowCreateChannelModal} /> <InviteWorkspaceModal show={showInviteWorkspaceModal} onCloseModal={onCloseModal} setShowInviteWorkspaceModal={setShowInviteWorkspaceModal} /> <InviteChannelModal show={showInviteChannelModal} onCloseModal={onCloseModal} setShowInviteChannelModal={setShowInviteChannelModal} /> </div> ); }; export default Workspace; 이건 제가 작성한 WorkSpace 입니다.import Modal from '@components/Modal'; import useInput from '@hooks/useInput'; import { Button, Input, Label } from '@pages/SignUp/styles'; import { IUser } from '@typings/db'; import fetcher from '@utils/fetcher'; import axios from 'axios'; import React, { FC, useCallback } from 'react'; import { useParams } from 'react-router'; import { toast } from 'react-toastify'; import useSWR from 'swr'; interface Props { show: boolean; onCloseModal: () => void; setShowInviteChannelModal: (flag: boolean) => void; } const InviteChannelModal: FC<Props> = ({ show, onCloseModal, setShowInviteChannelModal }) => { const { workspace, channel } = useParams<{ workspace: string; channel: string }>(); const [newMember, onChangeNewMember, setNewMember] = useInput(''); const { data: userData } = useSWR<IUser>('/api/users', fetcher); const { revalidate: revalidateMembers } = useSWR<IUser[]>( userData ? `/api/workspaces/${workspace}/channels/${channel}/members` : null, fetcher, ); console.dir(channel); const onInviteMember = useCallback( (e) => { e.preventDefault(); if (!newMember || !newMember.trim()) { return; } axios .post(`/api/workspaces/${workspace}/channels/${channel}/members`, { email: newMember, }) .then(() => { revalidateMembers(); setShowInviteChannelModal(false); setNewMember(''); }) .catch((error) => { console.dir(error); toast.error(error.response?.data, { position: 'bottom-center' }); }); }, [channel, newMember, revalidateMembers, setNewMember, setShowInviteChannelModal, workspace], ); return ( <Modal show={show} onCloseModal={onCloseModal}> <form onSubmit={onInviteMember}> <Label id="member-label"> <span>채널 멤버 초대</span> <Input id="member" value={newMember} onChange={onChangeNewMember} /> </Label> <Button type="submit">초대하기</Button> </form> </Modal> ); }; export default InviteChannelModal; 이건 제가 작성한 InviteChannelModal입니다.xhr.js:210 GET http://localhost:3090/api/workspaces/sleact/channels/undefined/members 404 (Not Found) dispatchXhrRequest @ xhr.js:210 xhrAdapter @ xhr.js:15 dispatchRequest @ dispatchRequest.js:58 request @ Axios.js:108 Axios.<computed> @ Axios.js:129 wrap @ bind.js:9 fetcher @ fetcher.ts:18 eval @ use-swr.js:392 step @ use-swr.js:43 eval @ use-swr.js:24 eval @ use-swr.js:18 __awaiter @ use-swr.js:14 eval @ use-swr.js:344 softRevalidate @ use-swr.js:532 onFocus @ use-swr.js:550 revalidate_1 @ use-swr.js:73 eval @ use-swr.js:77 eval @ web-preset.js:29그런데 위와 같은 에러가 발생합니다.콘솔에 channel을 출력해도 undefined가 뜹니다.. 그런데 url을 보면 http://localhost:3090/workspace/sleact/channel/테스트채널 이렇게 채널 명이 표시가 되는데 도대체 뭐 때문에 undefined라고 뜨는지 모르겠습니다... 아무리 찾아봐도 알 수가 없어서 글 남깁니다... 분명 WorkSpace의 route에도 오타가 없고 url도 표시가 잘되는데 왜 undefined일까요...
-
미해결Slack 클론 코딩[실시간 채팅 with React]
원래 깃허브에 올려주신 파일과 강의 파일이 다른가요...?
안녕하세요.먼저 제로초님 강의 보면서 공부 열심히 하고 있습니다. 감사합니다!. 현재 DMList 만드는 중인데 깃허브에 올려주신 front의 DMList와 제로초님이 강의하면서 작성하시는 DMList의 코드가 서로 다른 부분이 꽤 있던데 원래 그런가요...?영상을 정지해가면서 수정하고 있지만 안보이는 코드가 있어서 많이 헷갈리네요 ㅠㅠ
-
미해결프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
해쉬값과 캐쉬 갱신
'웹팩 기본편 - 자주 사용하는 로더'를 학습하고 있습니다.로더들 중에, file-loader에 대해 학습하다가 질문이 생겼습니다.웹팩이 .png파일을 발견하면 file-loader를 실행할 것이고, 로더가 동작하고 나면 아웃풋에 설정한 경로로 이미지 파일을 복사합니다. 그리고 파일명이 해쉬코드로 변경 됩니다. 수업시간에 강사님께서 쿼리스트링이 매번 바뀌는 해시값으로 설정된다고 하셨는데, 그러면 빌드를 할때마다 해시값이 매번 바뀌는 건가요?그리고 이게 캐시 관점에서 어떤 도움을 주는지 궁금합니다. 파일명이 해쉬코드로 변경되는게 캐쉬 갱신을 위한 처리로 보인다고 하셨는데, 정확히 어떤점에서 캐쉬 갱신에 도움을 주는지 이해가 잘 안가서요ㅠㅠ알려주시면 감사하겠습니다!
-
미해결프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
Hash 에러 발생
안녕하세요 강사님.제가 npm run build로 빌드를 하려고 할때마다 다음과 같은 에러가 생기더라구요..[에러 내용]$ npm run build > sample@1.0.0 build > webpack node:internal/crypto/hash:69 this[kHandle] = new _Hash(algorithm, xofLen); ^ Error: error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:69:19) at Object.createHash (node:crypto:138:10) at module.exports (C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\webpack\lib\util\createHash.js:135:53) at NormalModule._initBuildHash (C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\webpack\lib\NormalModule.js:417:16) at handleParseError (C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\webpack\lib\NormalModule.js:471:10) at C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\webpack\lib\NormalModule.js:503:5 at C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\webpack\lib\NormalModule.js:358:12 at C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\loader-runner\lib\LoaderRunner.js:373:3 at iterateNormalLoaders (C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\loader-runner\lib\LoaderRunner.js:214:10) at Array.<anonymous> (C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\loader-runner\lib\LoaderRunner.js:205:4) at Storage.finished (C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:55:16) at C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:91:9 at C:\Users\power\OneDrive\inflearn\devEnv\sample\node_modules\graceful-fs\graceful-fs.js:123:16 at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) { opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ], library: 'digital envelope routines', reason: 'unsupported', code: 'ERR_OSSL_EVP_UNSUPPORTED' } Node.js v20.3.0위의 에러가 왜 발생했는지 찾아봤고 원인과 해결방법을 다음 링크에 정리했습니다.[정리 링크] https://github.com/SeoMiYoung/Learning/issues/6결론적으로, npm run build를 하기전에export NODE_OPTIONS=--openssl-legacy-provider위의 명령어를 한번 쳐주고, npm run build를 하면, 제대로 빌드가 작동되더라구요..!그런데 VSCode를 다시 껐다 켜면, 또 다시 위의 명령어를 입력해준 다음에 빌드를 해야되더라구요..아마, 위의 명령어는 Node.js실행시, OpenSSL의 레거시 프로바이더를 사용하도록 환경변수를 설정해주는 명령어인데, 해당 명령어는 임시적으로 현재 세션에서만 레거시 프로바이더를 사용하도록 해주는 명령어이다보니, VSCode를 껐다 켜는것처럼, 재부팅하거나 새로운 세션을 시작하는 경우에는 환경변수가 초기화되어 다시 설정해줘야되는 것 같아서 그런 것 같더라구요..!재부팅할때마다 빌드하기전에 해당 명령어를 치고 시작하는게 번거롭습니다..혹시 해결 방법이 없을까요??[참고: 버전 정보]{ "name": "sample", "version": "1.0.0", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" }, "author": "", "license": "ISC", "description": "", "dependencies": { "css-loader": "^4.3.0", "file-loader": "^6.2.0", "react": "^18.2.0", "style-loader": "^1.3.0" }, "devDependencies": { "webpack": "^4.46.0", "webpack-cli": "^3.3.12" } }
-
해결됨프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
webpack.config.js에서의 CommonJS방식에 대한 질문
안녕하세요!수업시간에 보면 webpack.config.js 웹팩 설정파일을 CommonJS방식으로 작성하였는데요,웹팩은 Node.js에서 동작하는 프로그램이고,Node.js가 사용하는 모듈시스템이 CommonJS이므로 웹팩 설정파일을 CommonJS로 작성한 건 이해했습니다.그런데 문득 드는 궁금증이,CommonJS 모듈 시스템을 채택했던 NodeJS 환경에서 ES Module을 사용하려면 Babel과 같은 트랜스파일러(transpiler)를 사용했어야 했는데요. NodeJS 버전 13.2부터 ES모듈 시스템에 대한 정식 지원이 시작됨에 따라 다른 도구 없이 NodeJS에서 손쉽게 ES Module을 사용할 수 있게 되었잖아요..?그렇다면 노드버전 13.2부터는 webpack.config.js 를 CommonJS가 아닌, ES Module방식으로 작성해도 상관없는건가요?
-
해결됨프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
웹팩 버전
안녕하세요.현재 웹팩의 가장 최신버전이 5버전으로 알고 있는데,해당 강의에서는 4버전으로 진행하더라고요.제가 잘 몰라서 그런데.. 4버전으로 공부해도 상관은 없겠죠?
-
해결됨프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
웹팩-cli 버전을 명시하지 않으면 왜 에러가 날까요?
안녕하세요? 웹팩 cli를 처음 깔아보는 수강생입니다..npm install -D webpack@4 webpack-cli위의 코드처럼 그냥 webpack-cli를 깔면, 에러가 발생하는데요...그래서수업시간에 webpack-cli를 버전3을 사용한다는 글을 보고, 다음과 같이 명령어를 바꿔서 쳐보았더니npm install -D webpack@4 webpack-cli@3정상적으로 설치가 되었습니다. 왜 버전을 명시해주지 않으면 에러가 발생하나요?
-
해결됨프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)
import해오는 두가지 방법에 대해 제가 잘 이해한건지 확인받고 싶습니다!!
강사님께서, 수업중에 import해오는 방법을 두가지를 언급하셨는데요,import * as math from './math.js'; // [방법1] 모든 export를 math라는 객체로 가져오기 import { sum } from './math.js'; // [방법2] sum함수만 가져오기방법1로 import할 경우, sum함수를 사용하기 위해서 math.sum(,) 이렇게 써야하지만,방법2로 import할 경우, 그냥 바로 sum(,)으로 사용하면 되나요? 저는 일단 그렇게 이해하고 있는데그러면 import * as math1 from './math1.js'; import * as math2 from './math2.js';이렇게 math1.js와 math2.js에서 각각 sum함수를 만들고, 그걸 app.js에서 위와 같이 import해서 사용했을 때,math1.sum(,) 그리고 math2.sum(,) 이렇게 쓰면 되니깐, 이름이 sum으로 같아도 충돌이 안나겠네요? 그러나 방법2방식으로 import { sum } from './math1.js'; import { sum } from './math2.js';이렇게 가져온다면, 둘다 sum(,)으로 호출하게 되니깐, 이름 충돌이 발생하겠네요?제가 이해한것이 맞는지 확인부탁드려요ㅠㅠ
-
미해결Slack 클론 코딩[실시간 채팅 with React]
useSelector가 초기값만 읽고, 상태변화를 읽지못함
안녕하세요. 선생님늦은 시간인데도 답변해주셔서 감사합니다(꾸벅)선생님께서 말씀해주신대로 useSelector를 써봤는데요.useSelector가 초기값만 읽고, updateReducer에 의해 상태가 업데이트되면,업데이트 된 값을 읽지 못합니다....1. console.log(title)이라고 썼는데, 아무것도 뜨지 않습니다2. Modal 컴포넌트에 제목을 입력을 해도 상태 변화를 읽지를 못합니다.어디서 잘못 된걸까요??const TodoItem = () =>{ const [state, dispatch] = useReducer(checkReducer, todoItem) const id = useSelector((state)=> state.update.id); const title = useSelector((state)=> state.update.title) const content = useSelector((state)=> state.update.content); const isDone = useSelector((state)=> state.update.isDone) const handleCheck = (id) =>{ dispatch(checkBox(id)); }; console.log(title) return( <SeveralItemContainer> <TodoItemContainer key={id}> <TitleContainer> <img className ="dot" src={dot} alt="icon"></img> <div className="title">{title}</div> <img onClick={ () => {handleCheck(id)}} className="noncheck" src = {isDone ? check: noncheck} alt="icon"></img> </TitleContainer> <div className="contentcontainer"> <div className="content">{content}</div> </div> </TodoItemContainer> </SeveralItemContainer> ) }; export default TodoItem; export const updateReducer = (state=initialState, action)=>{ switch(action.type){ case 'UPDATE_TITLE': return{...state, title: action.payload}; case 'UPDATE_STARTDATE': return{...state, startDate: action.payload}; case 'UPDATE_ENDDATE': return{...state, endDate:action.payload}; case 'UPDATE_CONTENT': return {...state, content: action.payload}; case 'ADD_ITEM': return {...state, id: Number(state.id)+1} //여기서 todoItem을 바로 쓸 수 없다. state나 action관련된 변수만 넣어야 한다 // 배열은 가능하지만, 객체는 전개연산자(...)를 쓸 수 없다 default: return state; } }; const rootReducer = combineReducers({ update: updateReducer, check: checkReducer, }); export default rootReducer; const Modal = ({onClick}) =>{ const [state, dispatch] = useReducer(updateReducer, initialState) const handleModalClick = (e) => { e.stopPropagation(); // 이벤트 버블링 막기 }; //사용자가 입력한 값을 추적하는 함수 const handleInputChange = (e) =>{ const {name, value} = e.target; dispatch({type: `UPDATE_${name.toUpperCase()}`, payload: value}) }; //클릭으로 적은 모든 내용을 한번에 전달 const addItem = () =>{ dispatch({type:'ADD_ITEM'}); }; return( <ModalBackGround onClick={onClick}> <ModalView onClick={handleModalClick} > <div className = "titleContainer"> <img className="dot" src = {dot} alt="icon"></img> <input value ={state.title} name = "title" className="title" placeholder="메모 제목" onChange={handleInputChange}></input> <img onClick={addItem} className="edit" src={edit} alt="icon"></img> </div> <div className="date"> <div className='일자'>일자</div> <input value ={state.startDate} name ="startDate" className ="start" placeholder="시작일" onChange={handleInputChange}></input> <div>~</div> <input value ={state.endDate} name= "endDate" className ="end" placeholder="종료일" onChange={handleInputChange}></input> </div> <div className='contentContainer'> <textarea value ={state.content} name ="content" className ="content" placeholder="메모" onChange={handleInputChange}> </textarea> </div> </ModalView> </ModalBackGround> ) }; export default Modal;
-
미해결Slack 클론 코딩[실시간 채팅 with React]
리덕스에서 스토어 부분 질문
안녕하세요. 선생님선생님 말씀대로 useSelector를 사용해 보려고,로컬스토리지 관련 코드들은 삭제했습니다.원하는 구현기능)질문은 Modal 컴포넌트에서 리듀서에 의해 업데이트된 상태를,todoItem 컴포넌트로 가져와서 사용이 가능한가요?todoItem 컴포넌트로 가져와서 todoData에 집어넣고 싶습니다...그래서 updateReducer에서 ADD_ITEM case를 읽을때 그때 그 상태를todoItem 컴포넌트로 가져와서 사용이 하고 싶습니다.질문)1. 위에 기능을 useSelector만 알면 가능할까요?2. 리덕스에 4단계 액션, 디스패치, 리듀서, 스토어 중 스토어 부분,저장했다가 필요할때 꺼내쓰는 부분을 잘 모르겠어요.어떤 추가적인 개념 공부가 필요할 까요? const Modal = ({onClick}) =>{ const [state, dispatch] = useReducer(updateReducer, initialState) const handleModalClick = (e) => { e.stopPropagation(); // 이벤트 버블링 막기 }; //사용자가 입력한 값을 추적하는 함수 const handleInputChange = (e) =>{ const {name, value} = e.target; dispatch({type: `UPDATE_${name.toUpperCase()}`, payload: value}) }; //클릭으로 적은 모든 내용을 한번에 전달 const addItem = () =>{ dispatch({type:'ADD_ITEM'}); }; return( <ModalBackGround onClick={onClick}> <ModalView onClick={handleModalClick} > <div className = "titleContainer"> <img className="dot" src = {dot} alt="icon"></img> <input value ={state.title} name = "title" className="title" placeholder="메모 제목" onChange={handleInputChange}></input> <img onClick={addItem} className="edit" src={edit} alt="icon"></img> </div> <div className="date"> <div className='일자'>일자</div> <input value ={state.startDate} name ="startDate" className ="start" placeholder="시작일" onChange={handleInputChange}></input> <div>~</div> <input value ={state.endDate} name= "endDate" className ="end" placeholder="종료일" onChange={handleInputChange}></input> </div> <div className='contentContainer'> <textarea value ={state.content} name ="content" className ="content" placeholder="메모" onChange={handleInputChange}> </textarea> </div> </ModalView> </ModalBackGround> ) }; export default Modal; export const updateReducer = (state=initialState, action)=>{ switch(action.type){ case 'UPDATE_TITLE': return{...state, title: action.payload}; case 'UPDATE_STARTDATE': return{...state, startDate: action.payload}; case 'UPDATE_ENDDATE': return{...state, endDate:action.payload}; case 'UPDATE_CONTENT': return {...state, content: action.payload}; case 'ADD_ITEM': return {...state, id: Number(state.id)+1} //여기서 todoItem을 바로 쓸 수 없다. state나 action관련된 변수만 넣어야 한다 // 배열은 가능하지만, 객체는 전개연산자(...)를 쓸 수 없다 default: return state; } }; const TodoItem = () =>{ const [state, dispatch] = useReducer(checkReducer, todoItem) const [todoData, setTodoData] = useState(todoItem); const handleCheck = (id) =>{ dispatch(checkBox(id)); }; return( <SeveralItemContainer> { todoData.map((item)=>{ return ( <TodoItemContainer key={item.id}> <TitleContainer> <img className ="dot" src={dot} alt="icon"></img> <div className="title">{item.title}</div> <img onClick={ () => {handleCheck(item.id)}} className="noncheck" src = {item.isDone ? check: noncheck} alt="icon"></img> </TitleContainer> <div className="contentcontainer"> <div className="content">{item.content}</div> </div> </TodoItemContainer> ) }) } </SeveralItemContainer> ) }; export default TodoItem;
-
미해결Slack 클론 코딩[실시간 채팅 with React]
로그인 후 페이지가 뜨지 않습니다
Throttling navigation to prevent the browser from hanging. See <URL>. Command line switch --disable-ipc-flooding-protection can be used to bypass the protection Throttling navigation to prevent the browser from hanging. See https://crbug.com/1038223. Command line switch --disable-ipc-flooding-protection can be used to bypass the protection 계속 강의 잘 듣고 있었는데 며칠 전부터 이런 에러 메시지가 뜨면서 로그인해서 넘어가면 아무 화면도 뜨지 않습니다. git reset --hard로 이전 코드로 돌려놔봐도 전에는 잘 되던 코드도 지금 안됩니다.구글링해봐도 무슨 말인지 잘 모르겠는데 뭐가 문제일까요....
-
해결됨Slack 클론 코딩[실시간 채팅 with React]
초기 세팅이게 맞는건가요?
알려주신대로 세팅을 해봤는데, 이게 맞는건가요?강의에 보이는 선생님 세팅과 뭔가 다른것 같아서요 ㅜ첫번째 사진은 폴더를 펼치지 않은것, 나머지 사진은 폴더를 모두 열어제낀것 입니다이 상태로 다음 강의 진행해도 문제없을까요?
-
미해결Slack 클론 코딩[실시간 채팅 with React]
setSignUpError(error.response.data);에 data 가 TypeError: Cannot read properties of undefined (reading 'data')라고 뜹니다.
setSignUpError(error.response.data);이 부분의 data에 typeerror가 뜹니다.왜 뜨는지 검색을 해봐도 모르겠어서 질문 남깁니다.
-
미해결Slack 클론 코딩[실시간 채팅 with React]
안읽은메세지 표시
안녕하세요 제로초님mutate(0)으로 했는데도 콘솔찍어보니까 다시 1로 변합니다channel부분만 이러네요
-
해결됨Slack 클론 코딩[실시간 채팅 with React]
npm i typescript 충돌 오류
npm i typescript 작성 시 아래와 같은 오류가 뜹니다. 종속성 해결 과정에서 충돌이 발생한 것으로 보이는데, 여기서 --force를 해서 설치를 하면 실행 될 것 같긴한데 그렇게 했을때는 결국 문제가 터졌던 경험들이 있어서 어떻게 하면 되는지 잘 모르겠습니다./c/02WorkSpace/sleact/alecture (master)$ npm i typescriptnpm ERR! code ERESOLVEnpm ERR! ERESOLVE could not resolvenpm ERR!npm ERR! While resolving: react-custom-scrollbars@4.2.1npm ERR! Found: react@17.0.2npm ERR! node_modules/reactnpm ERR! peer react@">=16.8.0" from @emotion/react@11.10.6npm ERR! node_modules/@emotion/reactnpm ERR! peer @emotion/react@"^11.0.0-rc.0" from @emotion/styled@11.10.6npm ERR! node_modules/@emotion/stylednpm ERR! @emotion/styled@"^11.1.5" from the root projectnpm ERR! @emotion/react@"^11.1.5" from the root projectnpm ERR! peer react@">=16.8.0" from @emotion/styled@11.10.6npm ERR! node_modules/@emotion/stylednpm ERR! @emotion/styled@"^11.1.5" from the root projectnpm ERR! 10 more (@emotion/use-insertion-effect-with-fallbacks, ...)npm ERR!npm ERR! Could not resolve dependency:npm ERR! peer react@"^0.14.0 || ^15.0.0 || ^16.0.0" from react-custom-scrollbars@4.2.1npm ERR! node_modules/react-custom-scrollbarsnpm ERR! react-custom-scrollbars@"^4.2.1" from the root projectnpm ERR!npm ERR! Conflicting peer dependency: react@16.14.0 npm ERR! node_modules/reactnpm ERR! peer react@"^0.14.0 || ^15.0.0 || ^16.0.0" from react-custom-scrollbars@4.2.1npm ERR! node_modules/react-custom-scrollbars npm ERR! react-custom-scrollbars@"^4.2.1" from the root projectnpm ERR!npm ERR! Fix the upstream dependency conflict, or retrynpm ERR! this command with --force or --legacy-peer-depsnpm ERR! to accept an incorrect (and potentially broken) dependency resolution.npm ERR!npm ERR!npm ERR! For a full report see:npm ERR! C:\Users\KG.Park\AppData\Local\npm-cache\_logs\2023-05-16T00_56_02_463Z-eresolve-report.txtnpm ERR! A complete log of this run can be found in:
-
미해결Slack 클론 코딩[실시간 채팅 with React]
데이터 초기화 후
안녕하세요 제로초님 이미지가 안들어가져서 데이터를 삭제하고 다시 만들었는데 갑자기 잘되던것들이 이렇게 오류가 계속뜨네요. 아래는 현재 데이터 테이블들입니다
-
미해결Slack 클론 코딩[실시간 채팅 with React]
SWR Devtools 강의중
안녕하세요 제로초님 npm 사이트에서 devtools 보니까cache하고 mutate가 사라져있는데 swr하고 swr-devtools 버전을 강의하고 일치시키면 mutate 만되고 cache가 안됩니다!