묻고 답해요
130만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결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;
-
미해결웹 게임을 만들며 배우는 Vue
Vue.Js 3를 사용하시면 Vue.set , this.$set 메서드가 없습니다.
제로초님 강의를 보면서 현재 Vue.js 3를 가지고 학습 중에 있습니다.강의 내용을 보면서 저는 실시간으로 화면에 대한 변화가 일어나고 있길래 Vue.js 3에서 Vue.set과 this.$set을 확인한 결과 Vue.js 3 에서는 제거가 되었다고 알게 되었습니다.혹시 제로초님의 강의를 Vue.js 3로 들으시는 분들은 도움 되실 수 있지 않을까 해서 남깁니당
-
미해결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)를 지우고 실행해봐도 똑같은 결과가 나오는데 이 코드는 왜 있는 건가요?
-
미해결Slack 클론 코딩[실시간 채팅 with React]
DM 내용 표시하기
안녕하세요 강의중에 DM 내용 표시 하기 강의에서 map을 활용해 DM내용을 표시하는 부분인데 DM을 클릭하고 내용을 확인할 때 TypeError에러가 뜨면서 chatData.map is not a function 이라는 오류가 나오고 있습니다.. 혼자 해결하다 막혀서 질문 남겨 드립니다! DirectMessage.tsx (return 부분)return ( <Container> <Header> <img src={gravatar.url(userData.email, { s: '24px', d: 'retro' })} alt={userData.nicknam} /> <span>{userData.nickname}</span> </Header> <ChatList chatData={chatData} /> <ChatBox chat={chat} onChangeChat={onChangeChat} onSubmitForm={onSubmitForm} /> </Container> );chatList.tsximport React, { VFC, useCallback, useRef } from 'react'; import { ChatZone } from './styles'; import { IDM } from '@typings/db'; import Chat from '@components/Chat'; import { Scrollbars } from 'react-custom-scrollbars'; interface Props { chatData?: IDM[]; } const ChatList: VFC<Props> = ({ chatData }) => { const scrollbarRef = useRef(null); const onScroll = useCallback(() => {}, []); return ( <ChatZone> <Scrollbars autoHide ref={scrollbarRef} onScrollFrame={onScroll}> {chatData?.map((chat) => ( <Chat key={chat.id} data={chat} /> ))} </Scrollbars> </ChatZone> ); }; export default ChatList; chat.tsximport { IDM, IChat } from '@typings/db'; import React, { VFC, memo, useMemo } from 'react'; import gravatar from 'gravatar'; import { ChatWrapper } from './styles'; interface Props { data: IDM; } const Chat: VFC<Props> = ({ data }) => { const user = data.Sender; return ( <ChatWrapper> <div className="chat-img"> <img src={gravatar.url(user.email, { s: '36px', d: 'retro' })} alt={user.nickname} /> </div> <div className="chat-text"> <div className="chat-user"> <b>{user.nickname}</b> <span>{data.createdAt}</span> </div> <p>{data.content}</p> </div> </ChatWrapper> ); }; export default Chat;오류내용
-
해결됨Slack 클론 코딩[실시간 채팅 with React]
웹소켓은 프록시 사용 할 수 없나요?
`http://localhost:3095/ws-${workspace}`위 주소로는 잘 되는데 `/api/ws-${workspace}`로는 연결이 안됩니다. 웹소켓은 프록시 못쓰는건지,못쓴다면 혹시 왜 안되는건지 이유를 여쭈워도 괜찮을까요?
-
해결됨Slack 클론 코딩[실시간 채팅 with React]
Scss문법
styles.tsx파일을 보면& img {...}& > div {...}이렇게 있던데 '>' 기호가 있고 없고의 차이점은 뭔가요?
-
미해결Slack 클론 코딩[실시간 채팅 with React]
chat box가 위에 고정되어 있습니다.
DirectMessageimport React, { useCallback, useState } from 'react'; import gravatar from 'gravatar'; import { Container } from 'semantic-ui-react'; import { Header } from './styles'; import useSWR from 'swr'; import { useParams } from 'react-router'; import fetcher from '@utils/fetcher'; import ChatBox from '@components/ChatBox'; import useInput from '@hooks/useinput'; import axios from 'axios'; import { IDM } from '@typings/db'; import ChatList from '@components/ChatList'; const DirectMessage = () => { const { workspace, id } = useParams<{ workspace: string; id: string }>(); const { data: userData } = useSWR(`/api/workspaces/${workspace}/users/${id}`, fetcher); const { data: myData } = useSWR('/api/users', fetcher); const { data: chatData, mutate: mutateChat, revalidate, } = useSWR<IDM[]>(`/api/workspace/${workspace}/dms/${id}/chats?perPage=20&page=1`, fetcher); const [chat, onChangeChat, setChat] = useInput(''); const onSubmitForm = useCallback( (e) => { e.preventDefault(); console.log('chat'); if (chat?.trim()) { axios .post(`/api/workspaces/${workspace}/dms/${id}/chats`, { content: chat, }) .then(() => { revalidate(); setChat(''); }) .catch(console.error); } }, [chat], ); if (!userData || !myData) { return null; } return ( <Container> <Header> <img src={gravatar.url(userData.email, { s: '24px', d: 'retro' })} alt={userData.nicknam} /> <span>{userData.nickname}</span> </Header> <ChatList chatData={chatData} /> <ChatBox chat={chat} onChangeChat={onChangeChat} onSubmitForm={onSubmitForm} /> </Container> ); }; export default DirectMessage;ChatListimport React, { VFC } from 'react'; import { ChatZone, Section } from './styles'; import { IDM } from '@typings/db'; import Chat from '@components/Chat'; interface Props { chatData?: IDM[]; } const ChatList: VFC<Props> = ({ chatData }) => { return ( <ChatZone> {chatData?.map((chat) => { <Chat key={chat.id} data={chat} />; })} </ChatZone> ); }; export default ChatList; 보여드린 코드처럼 chatbox 중간에 chatlist를 넣게 되면 자동으로 아래로 내려갈 수 있게 했습니다.말씀대로 chatlist를 만들고 directmessage사이에 chatlist를 import 했습니다. 그런데 아래로 내려오지 않고 상단으로 그대로 고정되어 있어서 아무리 찾아보려고 해도 답이 안나오는거 같아 질문 남겨드립니다 ㅠ