묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결따라하며 배우는 리액트 테스트 [2023.11 업데이트]
es6 jest 미지원 오류 문의
안녕하세요 강의 잘 듣고 있습니다. 강의를 듣다가 axios를 설치하고 import 하는 과정에서 다음과 같은 문제가 발생했습니다. 구글링을 해보니 jest가 es6를 지원하지 않아서 발생하는 문제라고 하던데 구글링해서 찾아본 방법들은 해결이 되지 않아 문의 드립니다. FAIL src/pages/OrderPage/tests/Type.test.js ● Test suite failed to run Jest encountered an unexpected token Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax. Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration. By default "node_modules" folder is ignored by transformers. Here's what you can do: • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it. • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config. • If you need a custom transformation specify a "transform" option in your config. • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option. You'll find more details and examples of these config options in the docs: https://jestjs.io/docs/configuration For information about custom transformations, see: https://jestjs.io/docs/code-transformation Details: C:\Users\multicampus\Desktop\projects\react-test-app\react-shop-test\node_modules\axios\index.js:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import axios from './lib/axios.js'; ^^^^^^ SyntaxError: Cannot use import statement outside a module > 1 | import axios from 'axios'; | ^ 2 | import React, { useEffect, useState } from 'react' 3 | import { Products } from './Products'; 4 | at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14) at Object.<anonymous> (src/pages/OrderPage/Type.js:1:1) at Object.<anonymous> (src/pages/OrderPage/tests/Type.test.js:2:1) at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13) at runJest (node_modules/@jest/core/build/runJest.js:404:19)
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 유튜브 사이트 만들기
npm run dev 관련 오류
npm run dev를 하니 다음과 같은 오류가 납니다. PS C:\Users\82105\Downloads\boilerplate-mern-stack-master> npm run dev> react-boiler-plate@1.0.0 dev> concurrently "npm run backend" "npm run start --prefix client"[1] [1] > client@0.1.0 start[1] > react-scripts start[1][0][0] > react-boiler-plate@1.0.0 backend[0] > nodemon server/index.js[0][0] [nodemon] 1.19.4[0] [nodemon] to restart at any time, enter rs[0] [nodemon] watching dir(s): .[0] [nodemon] watching extensions: js,mjs,json[0] [nodemon] starting node server/index.js[0] (node:9916) Warning: Accessing non-existent property 'count' of module exports inside circular dependency[0] (Use node --trace-warnings ... to show where the warning was created)[0] Server Listening on 5000[0] (node:9916) Warning: Accessing non-existent property 'findOne' of module exports inside circular dependency[0] (node:9916) Warning: Accessing non-existent property 'remove' of module exports inside circular dependency[0] (node:9916) Warning: Accessing non-existent property 'updateOne' of module exports inside circular dependency[0] MongoDB Connected...[1] [HPM] Proxy created: / -> http://localhost:5000[1] i 「wds」: Project is running at http://192.168.123.163/[1] i 「wds」: webpack output is served from[1] i 「wds」: Content not from webpack is served from C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\public[1] i 「wds」: 404s will fallback to /[1] Starting the development server...[1][1] Error: error:0308010C:digital envelope routines::unsupported[1] at new Hash (node:internal/crypto/hash:71:19)[1] at Object.createHash (node:crypto:133:10)[1] at module.exports (C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\util\createHash.js:135:53)[1] at NormalModule._initBuildHash (C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:417:16) [1] at handleParseError (C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:471:10)[1] at C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:503:5[1] at C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:358:12[1] at C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:373:3[1] at iterateNormalLoaders (C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:214:10) [1] at iterateNormalLoaders (C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:221:10) [1] C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\react-scripts\scripts\start.js:19[1] throw err;[1] ^[1][1] Error: error:0308010C:digital envelope routines::unsupported[1] at new Hash (node:internal/crypto/hash:71:19)[1] at Object.createHash (node:crypto:133:10)[1] at module.exports (C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\util\createHash.js:135:53)[1] at NormalModule._initBuildHash (C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:417:16) [1] at C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:452:10[1] at C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\webpack\lib\NormalModule.js:323:13[1] at C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:367:11[1] at C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:233:18[1] at context.callback (C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\loader-runner\lib\LoaderRunner.js:111:13) [1] at C:\Users\82105\Downloads\boilerplate-mern-stack-master\client\node_modules\babel-loader\lib\index.js:59:103 {[1] opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],[1] library: 'digital envelope routines',[1] reason: 'unsupported',[1] code: 'ERR_OSSL_EVP_UNSUPPORTED'[1] }
-
해결됨풀스택 리액트 라이브코딩 - 간단한 쇼핑몰 만들기
react-query 에러
3강 학습 중 react-query 버전 문제로 인한 에러가 생겨 질문합니다.최신 버전으로 설치해서 react-query의 가이드 문서대로 코드를 수정했는데도 계속 에러가 나며 data를 가져오지 못 하고 있습니다.어떻게 해결해야 할지 모르겠습니다ㅜ첨부된 사진 외에는 강의대로 코드를 작성했으며 타입스크립트가 아닌 자바스크립트로 진행하고 있습니다.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
회원가입 안되시는분들
https://yamea-guide.tistory.com/entry/atlas-MongoError-user-is-not-allowed-to-do-action-find-on 이거땜에 2시간을 욕하고 힘들었네요 후... 어떤글도 해결이 안됐습니다 이거 따라하세요....
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
로그인 시도 시 타입에러 나는데 모르겠네요
TypeError: dispatch is not a functionat handleSubmit (login.tsx?11e1:23:13) 에러나는 부분은login파일의 dispatch("LOGIN",res.data?.user); 에서 에러가 납니다. 이 강의 듣는 몇몇분들도 동일하게 나타나는 증상같은데.. 확인 한번 부탁드립니다.
-
해결됨프론트엔드 개발자를 위한, 실전 웹 성능 최적화(feat. React) - Part. 1
번들파일과 병목현상 질문
안녕하세요 재밌게 강의 듣고 있습니다.번들파일을 분석하여 사용중인 모듈을 확인 하는 방법을 잘 알았습니다.code splitting을 통해 특정 페이지에서 필요없는 기능을 빼려는 이유도 잘 알겠습니다만.. 특정 페이지에서 사용하지 않는 기능은 어떻게 찾아낼 수 있을까요? 현업에선 엄청 많은 모듈과 기능들이 한 페이지 안에 담겨있을텐데 어디까지 쓰는 것이고 빼내야한다는 근거를 찾는 방법이 있나요? (시간 오래걸리는것만 빼내는건지.. 궁금합니다.) 두번 째로 병목 현상에 관련하여 GC의 경우도 이미 Article컴포넌트의 존재를 알고 그 안에 removespecial character가 1번만 일어나야된다는 것을 안다고 가정하고 GC가 여러번 일어난 것에 의심을 하는 것이 맞나요?GC랑 렌더링 성능시간이랑 크게 상관이 있는건지도 궁금합니다..!
-
해결됨프론트엔드 개발자를 위한, 실전 웹 성능 최적화(feat. React) - Part. 1
webpack-bundle-analyzer 질문
안녕하세요!customize-cra 를 사용해서 config-overrides.js 파일에서 BundleAnalyzerPlugin을 불러와서 사용하는데계속 에러가 나고 reports 파일을 확인할 수 없어서요 ㅠ addWebpackPlugin( new BundleAnalyzerPlugin({ analyzerMode: "static", openAnalyzer: true, generateStatsFile: true, statsFilename: "bundle-report.json", }) ),위 처럼 작성하고 script에 아래를 추가하고 yarn analyze를 했는데 에러가 나네요;; 뭐가 잘못된 걸까요? 조언 부탁드립니다 "analyze": "npx webpack-bundle-analyzer build/bundle-report.json",
-
미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
DiaryItem에 key={it.id}전달 이유
안녕하세요, 강의를 수강하다 궁금한 점이 있어 여쭤보려합니다. React에서 배열 사용하기 1 - 리스트 렌더링(조회) 강의 16분 35초 쯤 DiaryItem에 key={it.id}값을 전달하고 뒤에 {...it}을 전달하는 코드를 작성하게 되는데 {...it}을 전달하게 되면 it 내부에 있는 id도 같이 전달되게 되는데 굳이 key값에 it.id를 중복해서 전달하는 이유가 궁금합니다. 그래서 key={it.id}를 지워보았는데 코드는 동일하게 동작하였습니다. 이유가 무엇인가요?
-
해결됨풀스택 리액트 라이브코딩 - 간단한 쇼핑몰 만들기
uuid 에러
안녕하세요.수업을 듣던중에 같은 방법으로 uuid 라이브러리를 다운받고 실행을 하고있는데 이런 에러가 발생을 하고 있는데혹시 어떤 부분이 문제인지 알수있을까요..?@types/uuid 로 삭제 설치 다시 해보고 진행해도 계속 같은 에러가 발생합니다 ㅠ<package.json> "dependencies": { "@types/uuid": "^8.3.4", "graphql-request": "^5.0.0", "graphql-tag": "^2.12.6", "react": "^18.2.0", "react-dom": "^18.2.0", "react-query": "^3.39.2", "react-router-dom": "^6.4.3", "sass": "^1.56.1" },<handlers.ts>import { v4 as uuid } from "uuid"; const mock_products = Array.from({ length: 20 }).map((_, i) => ({ id: uuid(), imageUrl: `https://placeimg.com/200/150/${i + 1}`, price: 50000, title: `임시상품${i + 1}`, description: `임시상세내용${i + 1}`, createAt: new Date(1668159460287 + i * 1000 * 60 * 60 * 10).toString(), }));<에러 내용>[plugin:vite:import-analysis] Failed to resolve import "uuid" from "src\mocks\handlers.ts". Does the file exist? C:/Users/home/Desktop/배포/shop/shopping/src/mocks/handlers.ts:3:27 1 | import { graphql } from "msw"; 2 | import GET_PRODUCTS from "../graphql/products"; 3 | import { v4 as uuid } from "uuid"; | ^ 4 | const mock_products = Array.from({ length: 20 }).map((_, i) => ({ 5 | id: uuid(), at formatError (file:///C:/Users/home/Desktop/%EB%B0%B0%ED%8F%AC/shop/shopping/node_modules/vite/dist/node/chunks/dep-51c4f80a.js:39971:46) at TransformContext.error (file:///C:/Users/home/Desktop/%EB%B0%B0%ED%8F%AC/shop/shopping/node_modules/vite/dist/node/chunks/dep-51c4f80a.js:39967:19) at normalizeUrl (file:///C:/Users/home/Desktop/%EB%B0%B0%ED%8F%AC/shop/shopping/node_modules/vite/dist/node/chunks/dep-51c4f80a.js:36835:33) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async TransformContext.transform (file:///C:/Users/home/Desktop/%EB%B0%B0%ED%8F%AC/shop/shopping/node_modules/vite/dist/node/chunks/dep-51c4f80a.js:36968:47) at async Object.transform (file:///C:/Users/home/Desktop/%EB%B0%B0%ED%8F%AC/shop/shopping/node_modules/vite/dist/node/chunks/dep-51c4f80a.js:40224:30) at async loadAndTransform (file:///C:/Users/home/Desktop/%EB%B0%B0%ED%8F%AC/shop/shopping/node_modules/vite/dis
-
해결됨풀스택 리액트 라이브코딩 - 간단한 쇼핑몰 만들기
index.tsx에서 ProductItem부분에서 해당 반환 형식이 유효하지 않다고 할 때
index.tsx에서 ProductItem부분에서 해당 반환 형식이 유효하지 않다고 하면서 화면에 Display되지 않을때 어디를 확인하면 되는지 조언 부탁드립니다~데이터는 BASE_URL로 부터 잘 오고 있습니다mac에서 vsc사용하고 있습니다아래는 해당부분입니다import { useQuery } from "react-query" import ProductItem from "../../components/product/item" import { fetcher, QueryKeys } from "../../queryClient" import {Product} from "../../types" const ProductList = () => { const {data} = useQuery<Product[]>(QueryKeys.PRODUCTS, () => fetcher({ method: 'GET', path: '/products' }), ) /* id: 1 title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops" price: 109.95 description: "Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday" category: "men's clothing" image: "https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg" ▶ rating 2 items rate: 3.9 count: 120 */ return ( <div> <ul> {data?.map(product => ( <ProductItem {...product} key={product.id} /> ))} </ul> </div> ) //return (<div>상품목록</div>) } export default ProductListcomponents/product/item.tsx 파일입니다
-
미해결처음 만난 리액트(React)
npm start 이후 크롬창에 아무것도 뜨지않음
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.사진 첨부 순서대로 index.js, Comment.jsx, CommentList.jsx, npm start시 출력되는 크롬 화면입니다. 이전 시계 실습에서도 동일하게 빈 화면이 출력 됐는데 타 수강생님이 올려주신 코드를 적용하니 해결이 됐어서 다음 챕터를 진행하였습니다. 그런데 동일하게 빈화면이 출력되어 어떤 부분에서 문제가 있는지 도저히 찾을 수 없어서 질문드립니다.
-
해결됨프론트엔드 개발자를 위한, 실전 웹 성능 최적화(feat. React) - Part. 1
이미지 프리로딩 질문
강의에서 이미지url을 프리로딩하는것을 알려주셨는데 혹시 이미 리액트 폴더안에 에셋으로 넣어놓은 이미지 파일이나 폰트를 모달 띄우기 전에 미리 프리로딩 하는 방법을 알 수 있을까요?
-
미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
Deploy complete
강의와 같이 다 성공적으로 하고 firebase deploy 까지 완료 했는데 강사님처럼 도메인 주소 들어가면 프로젝트가 안뜨고 사지관 같이 뜹니다 ㅜㅠ
-
미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
마지막에 말씀하신 내용이 잘 이해가 안갑니다.
안녕하세요.강의를 듣다가 마지막에 하신 말씀이 잘 이해가 안돼서 질문드립니다.복잡한 상태 관리 로직 분리하기 - useReducer의 22:31 부분에서"dispatch는 함수형 업데이트 그런거 필요 없이 호출하면 알아서 현재의 state를 참조해서 자동으로 해주니 useCallback을 사용하면서 dependency array를 걱정할 필요가 없다."라고 하셨는데 이게 무엇을 의미하는 말씀인지 말 모르겠습니다...
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
drop table 후 질문드리겠습니다.
안녕하세요 제로초님 강의 잘듣고있습니다.배포는 처음이라 해당강의를 들으면서 무작정 따라하면서 실습을 하고 있습니다.근데 제가 모르고 drop table까지 따라해서 database가 삭제됬습니다.그래서 우분투 back으로 간 뒤 다시 db를 생성했습니다.근데 db는 정상적으로 생성이 됬는데 테이블을 검색해보면 다음과 같이 Empty set이 출력이 되더라고요이러한 경우에는 다시 인스턴스를 생성해야될까요? ㅜㅜ mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | recipe.io | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use recipe.io; Database changed mysql> show tables; Empty set (0.00 sec) mysql>
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
s3 배포시 Re-run all jobs 버튼 부재
Re-run all jobs 버튼이 없어서 node.js에서 오류가 발생하는데 혹시 어떻게 해야할까요?
-
미해결
redux-toolkit에서 createAsyncThunk 오류
안녕하세요 한참 검색하다 해결을 못해서 질문합니다.현재 vite를 통해 react를 돌리고 있는데 redux-toolkit으로 상태관리를 하고 있습니다.그러던 중 비동기 store를 만들기 위해 createAsyncThunk를 사용했는데컴퍼넌트내에서 호출 시Actions must be plain objects. Use custom middleware for async actions.다음과 같은 오류가 발생했습니다. 그래서 console에 값을 찍어보니 type과 action 대신creatorAction이라는 함수가 결과 값으로 나왔습니다.호출 시에 '변수명()'를 붙여주었는데도 다음과 같은 결과를 받았는데 해결 방안이 있는지 궁금합니다.(추가로 create-react-app으로 설치한 다른 폴더에서는 잘 작동됩니다.)
-
미해결비전공자를 위한 진짜 입문 올인원 개발 부트캠프
postman에서 no environment
postman에서 우측 상단의 no environment를 클릭해도다른 항목이 나오지 않습니다.
-
미해결따라하며 배우는 리액트 테스트 [2023.11 업데이트]
axios 1.1.2 버전 issue ( SyntaxError: Cannot use import statement outside a module)
혹시나 에러가 나신다면, package.json폴더에 "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"", "eject": "react-scripts eject" },로 변경 후 test를 종료 후 재 실행시키면 됩니다.방법은 test에서 직접 스크립트 수정하거나 jest.config.js파일을 만들어 moduleNameMapper을 사용하시면 됩니다!참고https://stackoverflow.com/questions/73958968/cannot-use-import-statement-outside-a-module-with-axioshttps://jestjs.io/docs/configuration#modulenamemapper-objectstring-string--arraystring
-
미해결Slack 클론 코딩[실시간 채팅 with React]
채널 생성시 channelData.map is not a function
채널생성 클릭하면 channeldata.map is not a function이라고 에러가 뜨는데channelData뿌려지는곳에 ?옵셔널도 줬고..아래처럼 잘 작성한것같은데 어딜 놓쳤는지 모르겠습니다.새로고침하면 추가된 채널명이 출력됩니다. workspaceimport fetcher from '@utils/fetcher'; import axios from 'axios'; import React, { FC, useCallback, useState } from 'react'; import { Navigate, useParams } from 'react-router-dom'; import useSWR from 'swr'; import { AddButton, Channels, Chats, Header, LogOutButton, MenuScroll, ProfileImg, ProfileModal, RightMenu, WorkspaceButton, WorkspaceModal, WorkspaceName, Workspaces, WorkspaceWrapper, } from './styles'; import gravatar from 'gravatar'; import Menu from '@components/menu'; import { Link } from 'react-router-dom'; import { IChannel, IUser, IWorkspace } from '@typings/db'; import { Button, Input, Label } from '@pages/signup/styles'; import useInput from '@hooks/useInput'; import Modal from '@components/modal'; import { toast } from 'react-toastify'; import CreateChannelModal from '@components/createChannelModal'; const Workspace: FC = ({ children }) => { const { workspace, channel } = useParams<{ workspace: string; channel: string }>(); const { data: userData, error, mutate } = useSWR<IUser | false>('/api/users', fetcher, { dedupingInterval: 2000 }); const { data: channelData } = useSWR<IChannel[]>(userData ? `/api/workspaces/${workspace}/channels` : null, fetcher); if (!userData) { return <Navigate to="/login" />; } const [showUserMenu, setShowUserMenu] = useState(false); const [newWorkspace, onChangeNewWorkspace, setNewWorkspace] = useInput(''); const [newUrl, onChangeNewUrl, setNewUrl] = useInput(''); const [showWorkspaceModal, setShowWorkspaceModal] = useState(false); const [showCreateChannelModal, setShowCreateChannelModal] = useState(false); const [showCreateWorkspaceModal, setShowCreateWorkspaceModal] = useState(false); //functions const onLogout = useCallback(() => { axios .post('/api/users/logout', null, { withCredentials: true, }) .then((res) => { mutate(res.data); }); }, []); const onClickUserProfile = useCallback(() => { setShowUserMenu(!showUserMenu); }, [showUserMenu]); const onClickCreateWorkspace = useCallback(() => { setShowCreateWorkspaceModal(true); }, []); const onCreateWorkspace = useCallback( (e) => { e.preventDefault(); if (!newWorkspace || !newWorkspace.trim()) return; if (!newUrl || !newUrl.trim()) return; //trim ->띄어쓰기 하나도 통과 돼버리는걸 막는다. axios .post( '/api/workspaces', { workspace: newWorkspace, url: newUrl, }, { withCredentials: true, }, ) .then((res) => { mutate(res.data); setShowCreateWorkspaceModal(false); setNewWorkspace(''), setNewUrl(''); }) .catch((err) => { console.dir(err); toast.error(error.response?.data, { position: 'bottom-center' }); }); }, [newWorkspace, newUrl], ); const onCloseModal = useCallback(() => { setShowCreateWorkspaceModal(false); setShowCreateChannelModal(false); }, []); const toggleWorkspaceModal = useCallback(() => { setShowWorkspaceModal(!showWorkspaceModal); }, [showWorkspaceModal]); const onClickAddChannel = useCallback(() => { setShowCreateChannelModal(true); }, []); 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 }} onCloseModal={onClickUserProfile} show={showUserMenu}> <ProfileModal> <img src={gravatar.url(userData.email, { s: '28px', 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: IWorkspace) => { 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> {channelData?.map((v, idx) => ( <div key={idx}>{v.name}</div> ))} </MenuScroll> </Channels> <Chats> {children}</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; createChannelModalimport Modal from '@components/modal'; import useInput from '@hooks/useInput'; import { Button, Input, Label } from '@pages/signup/styles'; import { IChannel, IUser } from '@typings/db'; import fetcher from '@utils/fetcher'; import axios from 'axios'; import React, { useCallback, VFC } from 'react'; import { useParams } from 'react-router-dom'; import { toast } from 'react-toastify'; import useSWR from 'swr'; 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<{ workspace: string; channel: string }>(); const { data: userData } = useSWR<IUser | false>(`/api/users`, fetcher); const { data: channelData, mutate } = useSWR<IChannel[]>( userData ? `/api/workspaces/${workspace}/channels` : null, fetcher, ); const onCreateChannel = useCallback( (e) => { e.preventDefault(); axios .post( `/api/workspaces/${workspace}/channels`, { name: newChannel, }, { withCredentials: true }, ) .then((res) => { setShowCreateChannelModal(false); mutate(res.data); setNewChannel(''); }) .catch((err) => { console.dir(err); toast.error(err.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;