묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨프론트엔드 개발환경의 이해와 실습 (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가 안됩니다!
-
미해결Slack 클론 코딩[실시간 채팅 with React]
안읽은메세지 개수 표시하기
안녕하세요 제로초님 디엠부분에서는 안읽은 메시지 표시가 떠서 읽으면 없어지는데채널부분에서는 없어지지않고 남아있습니다!
-
미해결Slack 클론 코딩[실시간 채팅 with React]
이미지 드래그 업로드하기 강의중
안녕하세요 제로초님Dm에서는 이미지가 드래그업로드가 되는데채널에서는 500에러가 뜹니다!백엔드코드 최신버전인데 바꿔야할것이 있나요?POST http://localhost:3095/api/workspaces/sleact/dms/%EC%9D%BC%EB%B0%98/images 500 (Internal Server Error)Error at Query.run (/Users/js/Desktop/sleact/back/node_modules/sequelize/lib/dialects/mysql/query.js:52:25) at /Users/js/Desktop/sleact/back/node_modules/sequelize/lib/sequelize.js:314:28 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async MySQLQueryInterface.insert (/Users/js/Desktop/sleact/back/node_modules/sequelize/lib/dialects/abstract/query-interface.js:308:21) at async DM.save (/Users/js/Desktop/sleact/back/node_modules/sequelize/lib/model.js:2432:35) at async DM.create (/Users/js/Desktop/sleact/back/node_modules/sequelize/lib/model.js:1344:12) at async /Users/js/Desktop/sleact/back/routes/api.js:522:20 POST /api/workspaces/sleact/dms/%EC%9D%BC%EB%B0%98/images 500 7.558 ms - 898
-
미해결Slack 클론 코딩[실시간 채팅 with React]
로그인 회원가입 둘다 cors 오류가 뜹니다 ㅠㅠ 도대체 뭐가 문제일까요..
안녕하세요~ 그전까지 잘되다가 오랜만에 다시 강의를 이어가려고하는데 갑자기 안됩니다 ㅠㅠ 뭐가 문제일까요..회원가입시에도 페이지가 넘어가지않고 계속 CORS 오류가 생기네요.. https://github.com/nuring9/react-SWR-SlackClone_front제가 따라한 코드 깃허브 주소올립니다 ㅠㅠ
-
미해결Slack 클론 코딩[실시간 채팅 with React]
SWR DevTools 관련
안녕하세요 SWR관련 질문이 있습니다.혹시 React 18버전에서는 SWR DevTools를 어떻게 사용할 수 있는지 부탁 드립니다.감사합니다.
-
미해결Slack 클론 코딩[실시간 채팅 with React]
채팅보내기 강의중
안녕하세요 제로초님!채팅보내기 강의를 보고있는데 workspace/index.tsx에서갑자기 socket 코드 가생겼는데 강의에는 설명이 없는거 같아서 문의 남깁니다!
-
미해결Slack 클론 코딩[실시간 채팅 with React]
str.toLowerCase is not a function
예상하지 못한 부분에서 에러가 나와서 질문 남겨드립니다 !ChatBox.tsximport React, { useCallback, useEffect, useRef, VFC } from 'react'; import { ChatArea, EachMention, Form, MentionsTextarea, SendButton, Toolbox } from './styles'; import autosize from 'autosize'; import { Mention, SuggestionDataItem } from 'react-mentions'; import { useParams } from 'react-router'; import useSWR from 'swr'; import { IUser } from '@typings/db'; import fetcher from '@utils/fetcher'; import gravatar from 'gravatar'; interface Props { chat: string; onSubmitForm: (e: any) => void; onChangeChat: (e: any) => void; placeholder?: string; } const ChatBox: VFC<Props> = ({ chat, onSubmitForm, onChangeChat, placeholder }) => { const { workspace } = useParams<{ workspace: string }>(); const { data: userData, error, revalidate, mutate, } = useSWR<IUser | false>('/api/users', fetcher, { dedupingInterval: 2000, // 2초 }); const { data: memberData } = useSWR<IUser[]>(userData ? `/api/workspaces/${workspace}/members` : null, fetcher); const textareaRef = useRef<HTMLTextAreaElement>(null); useEffect(() => { if (textareaRef.current) { autosize(textareaRef.current); } }, []); const onKeydownChat = useCallback( (e) => { if (e.key === 'Enter') { if (!e.shiftKey) { e.preventDefault(); onSubmitForm(e); } } }, [onSubmitForm], ); const renderSuggestion = useCallback( ( suggestion: SuggestionDataItem, search: string, highlightedDisplay: React.ReactNode, index: number, focus: boolean, ): React.ReactNode => { if (!memberData) return; return ( <EachMention focus={focus}> <img src={gravatar.url(memberData[index].email, { s: '20px', d: 'retro' })} alt={memberData[index].nickname} /> <span>{highlightedDisplay}</span> </EachMention> ); }, [memberData], ); return ( <ChatArea> <Form onSubmit={onSubmitForm}> <MentionsTextarea id="editor-chat" value={chat} onChange={onChangeChat} onKeyPress={onKeydownChat} placeholder={placeholder} inputRef={textareaRef} allowSuggestionsAboveCursor > <Mention appendSpaceOnAdd trigger="@" data={memberData?.map((v) => ({ id: v.id, display: v.nickname })) || []} renderSuggestion={renderSuggestion} /> </MentionsTextarea> <Toolbox> <SendButton className={ 'c-button-unstyled c-icon_button c-icon_button--light c-icon_button--size_medium c-texty_input__button c-texty_input__button--send' + (chat?.trim() ? '' : ' c-texty_input__button--disabled') } data-qa="texty_send_button" aria-label="Send message" data-sk="tooltip_parent" type="submit" disabled={!chat?.trim()} > <i className="c-icon c-icon--paperplane-filled" aria-hidden="true" /> </SendButton> </Toolbox> </Form> </ChatArea> ); }; export default ChatBox;혼자서 해결해보려다가 못찾고 있어서 질문 남겨드려요 ㅠㅠ
-
미해결Slack 클론 코딩[실시간 채팅 with React]
데이터 질문이요
const onSubmitForm = useCallback( (e) => { e.preventDefault(); if (chat?.trim() && chatData) { const savedChat = chat; mutateChat((prevChatData) => { prevChatData?.[0].unshift({ id: (chatData[0][0]?.id || 0) + 1, content: savedChat, SenderId: myData.id, Sender: myData, ReceiverId: userData.id, Receiver: userData, createdAt: new Date(), }); return prevChatData; }, false).then(() => { localStorage.setItem(`${workspace}-${id}`, new Date().getTime().toString()); setChat(''); if (scrollbarRef.current) { console.log('scrollToBottom!', scrollbarRef.current?.getValues()); scrollbarRef.current.scrollToBottom(); } }); axios .post(`/api/workspaces/${workspace}/dms/${id}/chats`, { content: chat, }) .then(() => console.log('first')) .catch(console.error); } }, [chat, workspace, id, myData, userData, chatData, mutateChat, setChat], ); const onMessage = useCallback( (data: IDM) => { if (data.SenderId === Number(id) && myData.id !== Number(id)) { mutateChat((chatData) => { chatData?.[0].unshift(data); return chatData; }, false) 이부분은 socket?.on('dm', onMessage) dm보내는 페이지에서 디엠을 보낼 때 onSubmitForm에서 mutate가 먼저 실행돼서 화면 데이터를 먼저 바꿔주고 그 다음 서버로 데이터를 보낸 뒤 처리하는 과정에서 socket.emit()이 실행되고 onMessage가 실행되는 걸로 이해했는데요. onMessage가 받는 데이터가 onSumbitForm의 mutate가 인자로 받는 함수랑 똑같아서 중복작업이 아닌가 싶어서 onMessage mutate 안의 chat.Data?.[0].unshift(data)를 지우고 실행해봐도 똑같은 결과가 나오는데 이 코드는 왜 있는 건가요?