soh308
@heyho
Reviews Written
-
Average Rating
-
Posts
Q&A
optimistic UI ์ค mutateChat ์์ Objects are not valid as a React child (found: Tue Nov 08 2022 17:24:47 GMT+0900 (ํ๊ตญ ํ์ค์)). If you meant to render a collection of children, use an array instead.
๋ฉ์์ง ๋ถ๋ถ์ chat ์ ๋ง์ํ์๋๊ฑธ๊น์? ใ data.createdAt์ ์ฃผ์์ฒ๋ฆฌํ๋๋ ์๋ฌ๊ฐ ๋ฐ๋๊ธด ํ์ด์ ๊ทผ๋ฐ ์๋ฌ๊ฐ ์ด๋์ ๋๋์ง ์๊ธฐ๊ฐ ์ด๋ ต๋ค์..import React, { memo, useMemo, VFC } from 'react'; import { ChatWrapper } from './styles'; import gravatar from 'gravatar'; import regexifyString from 'regexify-string'; import { Link, useParams } from 'react-router-dom'; interface Props { data: any; } // a?.b optional chaining // a??b nullish coalescing const Chat: VFC = ({ data }) => { const user = data.Sender; const { workspace } = useParams(); const result = useMemo( () => regexifyString({ input: data.content, pattern: /@\[(.+?)]\((\d+?)\)|\n/g, decorator(match, index) { const arr: string[] | null = match.match(/@\[(.+?)]\((\d+?)\)/)!; if (arr) { return ( @{arr[1]} ); } return ; }, }), [data.content], ); return ( (์ฌ์ง) {user.nickname} {/* {data.createdAt} */} {result} ); }; export default memo(Chat); (์ฌ์ง)import Chat from '@components/chat'; import { ChatZone, Section, StickyHeader } from '@components/chatList/styles'; import { IChat, IDM } from '@typings/db'; import React, { useCallback, forwardRef, ForwardedRef, RefObject, VFC } from 'react'; import { Scrollbars } from 'react-custom-scrollbars'; interface Props { chatSections: { [key: string]: IDM[] }; setSize: (f: (size: number) => number) => Promise; isReachingEnd: boolean; scrollRef: RefObject; } const ChatList: VFC = ({ chatSections, setSize, scrollRef, isReachingEnd }) => { const onScroll = useCallback( (values: any) => { if (values.scrollTop === 0 && !isReachingEnd) { console.log('๊ฐ์ฅ ์'); setSize((prevSize) => prevSize + 1).then(() => { // ์คํฌ๋กค ์์น ์ ์ง if (scrollRef?.current) { scrollRef.current?.scrollTop(scrollRef.current?.getScrollHeight() - values.scrollHeight); } }); } }, [scrollRef, isReachingEnd, setSize], ); return ( {Object.entries(chatSections).map(([date, chats]) => { return ( {date} {chats.map((chat) => ( ))} ); })} ); }; export default ChatList; import ChatBox from '@components/chatBox'; import ChatList from '@components/chatList'; import useInput from '@hooks/useInput'; import useSocket from '@hooks/useSocket'; import { Container, DragOver, Header } from '@pages/directMessage/styles'; import { IDM } from '@typings/db'; import fetcher from '@utils/fetcher'; import makeSection from '@utils/makeSection'; import axios from 'axios'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import gravatar from 'gravatar'; import Scrollbars from 'react-custom-scrollbars'; import { useParams } from 'react-router-dom'; import useSWR from 'swr'; import useSWRInfinite from 'swr/infinite'; import Workspace from '@layouts/workspace'; const DirectMessage = () => { const { workspace, id } = useParams(); console.log(id, 'id'); const { data: userData } = useSWR(`/api/workspaces/${workspace}/users/${id}`, fetcher); const { data: myData } = useSWR('/api/users', fetcher); const [chat, onChangeChat, setChat] = useInput(''); const { data: chatData, mutate: mutateChat, setSize, } = useSWRInfinite( (index) => `/api/workspaces/${workspace}/dms/${id}/chats?perPage=20&page=${index + 1}`, fetcher, ); const [socket] = useSocket(workspace); const isEmpty = chatData?.[0]?.length === 0; const isReachingEnd = isEmpty || (chatData && chatData[chatData.length - 1]?.length (null); const [dragOver, setDragOver] = useState(false); const onSubmitForm = useCallback( (e: any) => { e.preventDefault(); console.log(chat); 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(() => { setChat(''); scrollbarRef.current?.scrollToBottom(); }); axios .post(`/api/workspaces/${workspace}/dms/${id}/chats`, { content: chat, }) .then(() => { mutateChat(); }) .catch(console.error); } }, [chat, chatData, myData, userData, workspace, id], ); const onMessage = useCallback((data: IDM) => { // id๋ ์๋๋ฐฉ ์์ด๋ if (data.SenderId === Number(id) && myData.id !== Number(id)) { mutateChat((chatData) => { chatData?.[0].unshift(data); return chatData; }, false).then(() => { if (scrollbarRef.current) { if ( scrollbarRef.current.getScrollHeight() { scrollbarRef.current?.scrollToBottom(); }, 50); } } }); } }, []); useEffect(() => { socket?.on('dm', onMessage); return () => { socket?.off('dm', onMessage); }; }, [socket, onMessage]); // ๋ก๋ฉ ์ ์คํฌ๋กค๋ฐ ์ ์ผ ์๋๋ก useEffect(() => { if (chatData?.length === 1) { setTimeout(() => { scrollbarRef.current?.scrollToBottom(); }, 100); } }, [chatData]); const onDrop = useCallback( (e: any) => { e.preventDefault(); console.log(e); const formData = new FormData(); if (e.dataTransfer.items) { // Use DataTransferItemList interface to access the file(s) for (let i = 0; i { setDragOver(false); mutateChat(); }); }, [mutateChat, workspace, id], ); const onDragOver = useCallback((e: any) => { e.preventDefault(); console.log(e); setDragOver(true); }, []); if (!userData || !myData) { return null; } const chatSections = makeSection(chatData ? chatData.flat().reverse() : []); return ( (์ฌ์ง) {userData.nickname} {dragOver && ์ ๋ก๋!} ); }; export default DirectMessage;
- 0
- 2
- 587
Q&A
์ฑ๋ ์์ฑ์ channelData.map is not a function
์ฐ์ then ์์์ res.data ์ ๋ค์ด์ค๋๊ฑฐ ํ์ธํ๊ณ , mutate(res.data,false)๋ก swr์ด ์ ์ญ๊ด๋ฆฌํ๋๊ฑฐ๋ก ์ดํดํ๋๋ฐconst onCreateChannel = useCallback( (e) => { e.preventDefault(); axios .post( `/api/workspaces/${workspace}/channels`, { name: newChannel, }, { withCredentials: true }, ) .then((res) => { setShowCreateChannelModal(false); mutate(res.data, false); console.log(res.data, 'res.data'); setNewChannel(''); }) .catch((err) => { console.dir(err); toast.error(err.response?.data, { position: 'bottom-center' }); }); }, [newChannel], ); (์ฌ์ง)์ด๋ ๊ฒ ์ฐ์ด๋ณด๋ฉด (์ฌ์ง)๋ฐฐ์ด์ด ํ๋ฆฌ๋ฉด์? ์๋ฌ๋๋ ๊ฒ ๊ฐ์ต๋๋ค..(์ฌ์ง)์ด๋ฐ์์ผ๋ก ์ฒ๋ฆฌํด์ค์ผ ํ๋ ํด๋ดค๋๋ฐ ์๋๊ฒ๊ฐ๊ณ ...๊ณ ๋ฏผ ๊ณ์ ํด๋ณด๊ฒ ์ต๋๋ค..
- 0
- 3
- 552
Q&A
๋ก๊ทธ์ธ -> workspace๋ก ์ด๋ํ์ง ์๋ ์ด์
ใ ใ login์์ onSubmit ์์ชฝ๊ณผ ๋ฐ๊นฅ์ชฝ์ ,fetcher์ ์ฝ์์ ์ถ๊ฐํ์ฌ ์คํํด๋ดค์ต๋๋ค.import axios from 'axios'; const fetcher = (url: string) => { axios .get(url, { withCredentials: true, // withCredentials: true, proxy๋ฅผ ์์จ์ ๋ฐฑ์๋, ํ๋ก ํธ ํฌํธ๊ฐ ๋ค๋ฅด๋ฉด ์ฟ ํค๋ฅผ ์ ๋ฌํ ์ ์์. ๋ก๊ทธ์ธ์ด ๋๋์ง ํ์ธ๋ถ๊ฐ. ๊ทธ๋์ ์ด๊ฑฐ๋ก ํด๊ฒฐ. }) .then((response) => console.log(response.data, '์๋ต')); }; export default fetcher; import useInput from '@hooks/useInput'; import React, { useCallback, useState } from 'react'; import { Header, Button, Error, Form, Input, Label, LinkContainer, Success } from '@pages/signup/styles'; import { Link, Navigate } from 'react-router-dom'; import axios from 'axios'; import useSWR from 'swr'; import fetcher from '@utils/fetcher'; const LogIn = () => { const { data, error, mutate } = useSWR('/api/users', fetcher); const [logInError, setLogInError] = useState(false); const [email, onChangeEmail] = useInput(''); const [password, onChangePassword] = useInput(''); const onSubmit = useCallback( (e) => { e.preventDefault(); setLogInError(false); axios .post( '/api/users/login', { email, password }, { withCredentials: true, }, //get์ผ๋์ post์ผ๋ withCredentials ์์น๊ฐ ๋ค๋ฅด๋ค. ) .then((response) => { console.log(response.data, 'onSubmit์์์'); mutate(response.data); }) .catch((error) => { setLogInError(error.response?.data?.statusCode === 401); }); }, [email, password], ); console.log(data, 'login์ปดํฌ์์'); if (data) { return ; } return ( Sleact ์ด๋ฉ์ผ ์ฃผ์ ๋น๋ฐ๋ฒํธ {logInError && ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ ์กฐํฉ์ด ์ผ์นํ์ง ์์ต๋๋ค.} ๋ก๊ทธ์ธ ์์ง ํ์์ด ์๋์ ๊ฐ์? ํ์๊ฐ์ ํ๋ฌ๊ฐ๊ธฐ ); }; export default LogIn; import fetcher from '@utils/fetcher'; import axios from 'axios'; import React, { FC, useCallback } from 'react'; import { Navigate } from 'react-router-dom'; import useSWR from 'swr'; const Workspace: FC = ({ children }) => { const { data, error, mutate } = useSWR('/api/users', fetcher); const onLogout = useCallback(() => { axios .post('/api/users/logout', null, { withCredentials: true, }) .then((res) => { mutate(res.data); }); }, []); if (!data) { return ; } return ( ๋ก๊ทธ์์ {children} ); }; export default Workspace; (์ฌ์ง)(์ฌ์ง)์๋ก๊ณ ์นจ ํ๋ฉด fetcher๊ฐ ์๋๋๋ฉด์๋ ๋ฐ์ดํฐ๊ฐ ์ฐํ๋๋ฐ๋ก๊ทธ์ธ ์ปดํฌ๋ํธ์์ useSWR์ data๊ฐ ๊ณ์ ์ด๊ธฐํ๊ฐ ๋๋ ๊ฒ ๊ฐ์๋ฐ..๊ณ์ ๊ณ ๋ฏผํด๋ณด๊ฒ ์ต๋๋ค.. ใ ๋ญ๊น์.. ๋ค๋ฅธ ๋๊ธ ๋ณด๋๊น ์กฐ๊ฑด์ data===false ๋ก ํด๋ณด๋ผ๊ณ ํ์ ๊ฑฐ ๋ณด๊ณ ํด๋ณด๋(์ฌ์ง)์ด๋ฐ ํ์ ์๋ฌ๊ฐ ๋จ๋ค์...ใ ใ
- 0
- 2
- 519
Q&A
proxy 504 ์๋ฌ
(์ฌ์ง)npm run dev๋ก ์ด์๊ณ ์ด๋ ๊ฒ ์ด๋ ค์๋๊ฒ ์ผ์ง์ํ ๋ง์ง์๋์?
- 0
- 2
- 796
Q&A
findOne(id) ์์ ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ํด๊ฒฐ๋ฒ
findOneBy({id}) ๊ฐ๋ค์.. fineOne์ด ์๋๋ผ..
- 23
- 6
- 3.5K




