묻고 답해요
131만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨실무에 바로 적용하는 프런트엔드 테스트 - 1부. 테스트 기초: 단위・통합 테스트
shopping-mall-integration-test 브랜치에 이상한 점 발견
4.6 RTL 비동기 유틸 함수를 통한 노출 테스트 작성 강의 수강중 문제 발견shopping-mall-integration-testshopping-mall-integration-test-answer 두 브랜치 사이에 테스트 코드가 아닌 부분이 차이가 있는 것을 발견했습니다. ProductCard.jsx 파일강의 내용과는 상관 없는 부분이 소스코드가 달라서에러가 발생하는 것을 확인했습니다. 이마저도 테스트 코드를 통해 검증하긴 했지만처음에는 제가 테스트 코드가 익숙치 않아 잘못하고 있는 건가 싶었네요. 해당 부분 확인 한번 부탁드릴게요.
-
미해결웹 게임을 만들며 배우는 React
비동기로 동작하는 setState에 대해서
안녕하세요 제로초님setState 질문이 있는데요아래 코드에서 1번 코드의 경우 setState함수는 비동기라서 해당 이벤트 함수가 실행된 후 setState함수를 모아서 일괄 처리하기 때문에 +3이 아닌 +1로 렌더링된다 라고 알고 있는데요2번 코드에서는 왜 +3으로 렌더링되는지 이해가 되지 않아서요. setNum((prev) => prev + 1) 처럼 이전 state 값을 받아오는 형태도 아닌데 어떤 원리로 1번 코드와 2번 코드가 서로 다르게 동작하는 것인지 궁금합니다 import React, {useState} from 'react'; export function App(props) { let [num, setNum] = useState(0); const increase1 = () => { // 1번 코드 setNum(num + 1); setNum(num + 1); setNum(num + 1); // 2번 코드 setNum(num = num + 1); setNum(num = num + 1); setNum(num = num + 1); console.log(`${num}번째 1+ 이벤트 발생 ---> num: ${num}`); } console.log(`렌더링 ---> num : ${num}`); return ( <div className='App'> <button type="button" onClick={increase1}>+1</button> <p>{num}</p> </div> ); }
-
해결됨[리액트 2부] 고급 주제와 훅
[4.4장 메모이제이션 훅] 4.4.2 useMemo 에서 every 함수에 관한 질문입니다.
안녕하세요 선생님 every 배열을 비교하는 방법이 궁금해서 로그를 찍어보았습니다.// export default App; import MyReact from "./lib/MyReact"; import React from "react"; const Board = ({ posts, tag }) => { MyReact.resetCursor(); const [darkTheme, setDarkTheme] = React.useState(false); const filterPosts = () => { console.log("filterPosts"); return posts.filter((post) => (tag ? post.tag === tag : true)); }; const filteredPosts = MyReact.useMemo(filterPosts, [posts, tag]); console.log("Board rendered"); return ( <> <div> <button onClick={() => setDarkTheme(!darkTheme)}>Theme Change</button> <span>{darkTheme ? "dark" : "light"}</span> </div> <FilteredPosts value={filteredPosts}></FilteredPosts> </> ); }; const FilteredPosts = MyReact.memo(({ value }) => { console.log("FilteredPosts rendered") return ( <ul> {value.map(({ id, content, tag }) => { return ( <li key={id}> {content} <span>#{tag}</span> </li> ); })} </ul> ); }); export default () => { const [tag, setTag] = React.useState(""); return ( <> <button onClick={() => setTag("")}>ALL</button> <button onClick={() => setTag("tag1")}>Tag1</button> <button onClick={() => setTag("tag2")}>Tag2</button> <Board posts={[ { id: "id1", content: "content1", tag: "tag1" }, { id: "id2", content: "content2", tag: "tag1" }, { id: "id3", content: "content3", tag: "tag2" }, ]} tag={tag} /> </> ); }; function useMemo(nextCreate, deps) { console.log("deps = ", deps); if (!memorizedStates[cursor]) { const nextValue = nextCreate(); memorizedStates[cursor] = [nextValue, deps]; cursor = cursor + 1; return nextValue; } const nextDeps = deps; const [prevValue, prevDeps] = memorizedStates[cursor]; console.log("prevDeps => ", prevDeps); console.log("nextDeps => ", nextDeps); if ( prevDeps.every((prev, index) => { console.log( "comparing -> ", prev, nextDeps[index], prev === nextDeps[index], index ); return prev === nextDeps[index]; }) ) { console.log("it is same"); cursor = cursor + 1; return prevValue; } console.log("it is not same"); const nextValue = nextCreate(); memorizedStates[cursor] = [nextValue, deps]; cursor = cursor + 1; return nextValue; }여기서 궁금한 점은1번째 빨간 paragraph는 theme change를 눌러서 변경이 없는 경우입니다. comparing => 로그를 확인하면every가 2개를 비교하는데 첫번째는 array(posts)를 비교하고두번째는 tag를 비교하는것을 확인 할 수 있습니다. 2번째 빨간 paragraph는 Tag1 버튼을 누른 경우입니다.이때 저는 첫번째 비교는 true이고 두번째 비교에서 빈문자열 vs tag1이니 여기서 false가 나길 기대했지만 결과는 그렇지 않았고 첫번째 array(posts) 비교에서 false가 나왔습니다. 3번째 빨간 paragraph는 다시 theme change를 눌렀고 이는 정상적으로 array(posts) , tag1 비교를 수행한것을 확인할 수 있습니다. 왜 이런것인가요?
-
해결됨풀스택 리액트 토이프로젝트 - REST, GraphQL (for FE개발자)
프로젝트 배포
내용 정리해서 프로젝트로 사용하고 싶어서요로컬에서만 돌릴 수 있고 따로 배포하거나 할 수는 없나요??
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
DB에서 Comment 테이블이 안불러와지는 것 같습니다.
// posts.jsrouter.get("/", async (req, res, next) => { // GET /posts console.log(Comment); try { const posts = await Post.findAll({ limit: 10, order: [["createdAt", "DESC"]], include: [ { model: User, attributes: ["id", "nickname"], }, { model: Image, }, { model: Comment, include: [ { model: User, attributes: ["id", "nickname"], }, ], }, ], }); res.status(200).json(posts); } catch (error) { console.error(error); next(error); } }); module.exports = router;LOAD_POST_REQUEST 액션이 dispatch돼서api 요청을 통해 data를 받아오면 data안에 Comments의 값이 Comments 테이블에 들어있는 값이 들어있을 것으로 예상이 되는데 빈배열인 상황입니다. 혹시 다른 살펴볼만한 곳이 있는지 알려주시면 감사하겠습니다. 감사합니다.
-
미해결MERN 스택으로 만드는 지도서비스(+ TypeScript)
카카오 맵 api
안녕하세요 혹시 앞으로 강의를 진행하는데 카카오 api를 사용해도 큰문제는 없을까요
-
미해결만들면서 배우는 리액트: 컴포넌트 설계와 리팩토링
<> </> 의미
function App() { const [count, setCount] = useState(0) return ( <> ... </> ) }제가 놓쳤을수도 있는데, <> , </> 의미를 뒷부분에 설명한다고 했는데, 끝까지 설명이 안나온것 같습니다.
-
미해결웹 게임을 만들며 배우는 React
npm run dev 할 때 에러발생
에러메세지: [webpack-cli] Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema. - configuration.module.rules[0] has an unknown property 'mode'. These properties are valid: object { assert?, compiler?, dependency?, descriptionData?, enforce?, exclude?, generator?, include?, issuer?, issuerLayer?, layer?, loader?, mimetype?, oneOf?, options?, parser?, realResource?, resolve?, resource?, resourceFragment?, resourceQuery?, rules?, scheme?, sideEffects?, test?, type?, use? } -> A rule description with conditions and effects for modules. webpack.config.js 파일 코드const path = require("path"); //path: 노드에서 경로 조작하는 것을 쉽게 해준다. const RefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin"); module.exports = { name: "wordrelay", mode: "development", // 실서비스: production devtool: "eval", // 실서비스: hidden-source-map resolve: { extensions: [".js", ".jsx"], //이렇게 적으면 웹펙이 알아서 js나 jsx가 있는지 확인을 하고, react-react-to-dom-word-relay 이거 찾아서 app.js로 만들어준다. }, // 입력 entry: { app: ["./client"], }, module: { rules: [ { test: /\.jsx?$/, //정규표현식: JS랑 JSX 파일에 룰을 적용하겠다. loader: "babel-loader", mode: "development", options: { //babel-loader의 옵션 presets: [ [ "@babel/preset-env", { targets: { browsers: ["> 1% in KR"], // browserslist }, debug: true, }, ], "@babel/preset-react", ], plugins: [ "@babel/plugin-proposal-class-properties", "react-refresh/babel", ], }, }, ], }, plugins: [new RefreshWebpackPlugin()], //출력 output: { path: path.join(__dirname, "dist"), //컴퓨터 마다 파일 경로가 다 다른데 현재폴더안에 자동으로 dist폴더를 만들어준다. filename: "app.js", publicPath: "/dist/", }, devServer: { publicPath: '/dist/', hot: true, devMiddleware: { publicPath: "/dist" }, static: { directory: path.resolve(__dirname) }, }, //터미널에 webpack쓰면 두 파일을 합쳐준다. }; package.json 코드 { "name": "lecture", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "webpack --mode development", "dev": "webpack serve --env development", "assets": "webpack --config webpack.config.js --mode development" }, "author": "tk", "license": "MIT", "devDependencies": { "@babel/core": "^7.24.0", "@babel/preset-env": "^7.24.0", "@babel/node": "^7.23.9", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "react-refresh": "^0.14.0", "webpack": "^5.90.3", "webpack-cli": "^7.23.9", "webpack-dev-server": "^5.0.3" }, "dependencies": { "babel-loader": "^9.1.3", "react": "^18.2.0", "react-dom": "^18.2.0" } } 호환문제인 것같은데 어떤 부분이 호환문제가 생기는건지 잘 모르겠습니다.
-
미해결Next + React Query로 SNS 서비스 만들기
[react-query] queryClient.prefetchQuery 사용목적 구분이 헷갈립니다.
message페이지 수정하기편에서 queryClient.prefetchQuery를 사용했는데 다른 컴포넌트에서 queryClient. prefetchQuery를 사용할때는 HydrationBoundary컴포넌트로 감싸고 state에 fetching 해온 데이터를 주입시켜서 사용했는데 여기서는 왜 아무곳에서도 사용하고 있지 않은건지 궁금합니다.그리고 HydrationBoundary컴포넌트로 감싸고 state에 fetching해온 데이터를 주입시켜서 사용하고 있는곳들도 자식 컴포넌트에서 또 useQuery를 사용하는데 부모 HydrationBoundary에 접근해서 데이터를 사용하지 않고 useQuery로 fetching해와서 사용하는건지 궁금합니다. 저는 여태 HydrationBoundary가 fetching해온 데이터를 공유해주는 ContextAPI같은 컴포넌트라고 생각했었습니다. 자식컴포넌트에서 일일이 useQuery로 데이터를 가져오는거면 상위에 HydrationBoundary컴포넌트 안만들어줘도 되는거 아닌가요?
-
해결됨만들면서 배우는 리액트: 컴포넌트 설계와 리팩토링
handler 정의시 const 로 정의하는것과 function으로 정의하는것 차이
안녕하세요, 섹션2 "할 일 저장 기능 구현" 강의를 보다가 function으로 handler를 정의하는것과const 로 정의하는것과 동작상에는 차이가 없는것 같은데,const로 정의하는 특별한 이유가 있나요?
-
미해결만들면서 배우는 리액트: 컴포넌트 설계와 리팩토링
질문있습니다 (SSR 빌드)
안녕하세요, 강의 첫부분 프로젝트 생성 강의 중에 궁금해서 질문남깁니다. React는 이제 install 에는 next.js (SSR)과 같은 기법으로 프로젝트 생성하는 방법만 제안하는것인가요?홈페이지에 떡하니 윗부분에 있길래 그런생각이 들었습니다. 기존 CSR같은 방법도 홈페이지 메뉴얼에 있을법한데, 왜 next.js를 default (젤 윗부분)에 있고, CSR 방법은 메뉴얼에 없는지 궁금합니다. 참고로 svelte 도 잠시 공부해봤는데, sveltekit이란 빌드도구도 기본 SSR로 되도록 동작하는거같더라고요..
-
해결됨실무에 바로 적용하는 스토리북과 UI 테스트
Interaction 테스트 강의 설치 문제
안녕하세요. 이전글에 이어서 Interaction 테스트를 하는 과정에서 발생한 이슈 공유드립니다. [명령어가 다른 문제]확인해보시면 아시겠지만, Interaction 테스트를 위해 강의에서 설치한 명령어와 현재 공식문서에 작성되어있는 명령어가 다릅니다.강의: @storybook/jest, @storybook/testing-library문서: @storybook/test설치항목이 줄어들었지만, 최신화된 공식문서의 내용을 따라가도 정상적으로 동작함을 확인했습니다. [스토리북 실행시 에러 발생]No matching export in "global-externals:@storybook/components스토리북을 실행하면 상단에 작성한 문제가 발생할 수 있는데, 저의 경우에는 .nodemodules 디렉토리를 삭제하고 @storybook/components @storybook/addons먼저 설치한 후 다시 공식문서에서 제공하는 명령어를 통해 설치하여 해결했습니다. 하단의 링크를 참고하시면 됩니다.https://github.com/storybookjs/storybook/issues/24906 (+추가적으로 @storybook/vue3 를 설치해야 Meta, StoryObj를 불러올 수 있습니다.) [스토리북 테스트 실패]LoginForm 컴포넌트와 스토리를 만드는 과정에서 코드를 복사하여 가져올 때, EmptyForm과 FilledForm의 render 부분을 주석처리해야 테스트가 통과됨을 확인했습니다.
-
해결됨[React / VanillaJS] UI 요소 직접 만들기 Part 1
class 자동완성 방법은 없을까요?
classnames/bind 를 사용하지 않고, classnames를 사용할 때, typescript-plugin-css-modules 라는 것을 사용하면 위와 같이 현재 scss파일 안에 있는 클래스들이 보여지게 되는데요! classnames/bind 를 통해 cx를 만들어 사용할 때도 클래스들이 자동완성 됐으면 좋겠다고 생각이 들었습니다. 혹시 이것에 대한 방법이 있을까요?
-
해결됨실무에 바로 적용하는 스토리북과 UI 테스트
스토리북 테스트 실패 및 워크플로우 무기한 중단 문제 (Accessibility 테스트 강의)
안녕하세요. 제가 강의에서 놓친 부분일 수도 있겠지만, 스토리북 테스트 실패 및 워크플로우 무기한 중단 문제에 대해서 제가 해결한 방법을 공유드립니다. [노드 버전]상단의 이미지처럼 워크플로우가 돌아가면서 노드 버전으로 인해 발생한 문제는 .nvmrc 파일에 작성된 노드버전을 조정하여 해결했습니다. (저의 경우에는 18.18.0) [워크플로우]상단의 이미지는 워크플로우가 다음 단계로 넘어가지 않아 직접 워크플로우를 취소한 화면인데, 이 문제는 워크플로우의 스크립트를 수정하여 해결했습니다.npx wait-on tcp:127.0.0.1:6006 && yarn test-storybook해당 문제는 노드 버전으로 인해 발생된 것으로 보이며, 자세한 내용은 하단의 링크를 통해 확인하실 수 있습니다.https://github.com/storybookjs/test-runner/issues/301 [스토리북 테스트 실패]스토리북 테스트 명령어를 로컬에서 돌릴 경우, 강의를 따라가면서 생성한 스토리들과 컴포넌트에서는 문제가 없었으나,Header, Page, LoggedIn(Smoke-test), LoggedOut(Smoke-test)... 위와 같은 파일들에서 문제가 발생하는데, 해당 파일들을 모두 삭제하여 해결했습니다.
-
미해결iOS/Android 앱 개발을 위한 실전 React Native - Basic
환경변수 및 SOURCE관련 질문
좋은 강의 잘 듣고, 하나하나 따라하고 있는 코린이 입니다.다름이 아니라 환경변수는 왜 설정해줘야하는 지 궁금합니다.그리고 bash_profile관련해서 source bash_profile을 해주셨는데, 그 과정이 왜 필요한 지 어떤 것들이 일어나고 있는 지 궁금합니다.
-
미해결iOS/Android 앱 개발을 위한 실전 React Native - Basic
글로벌로 설치한다는 게 무슨 말인가요? (-g)
npm install -g react-native-cli 에서 -g는 글로벌로 설치한다고 하셨는데,글로벌로 설치한다는 게 뭇느 말인가요?그런-g를 사용하지 않으면 어떤 일이 벌어지나요?
-
미해결(2024 최신 업데이트)리액트 : 프론트엔드 개발자로 가는 마지막 단계
json-server 최신버전이면 검색이 안나올 수 있습니다.
json-server 터미널에서json-server --version 확인 후 강사님(0.17.0)과 다르다면 검색할 때 제품이 안나올 수 있습니다.npm uninstall -g json-server 서버 삭제 후npm install -g json-server@0.17.0 버전으로 다시 설치 하시면 정상적으로 잘 나오네요
-
미해결[리액트 2부] 고급 주제와 훅
[4.3장 리듀서 훅] 4.3.7 활용 MyForm(풀이) 오타 제보 및 질문이 있습니다.
안녕하세요 선생님 코드에 오타가 있습니다.const formReducer = (state, action) => { if (action.type === "SET_VALUES") { console.log("SET_VALUES, state ", state); return { ...state, values: { ...state.values, //value --> values [action.name]: action.value, }, }; }value에서 values로 수정되어야 할 것 같습니다. 질문:1) value 인 상태에서는 전화번호에 숫자를 입력했을 때 onChange event에 의해서 state가 변경이 됨2) 이때 state.value는 undefined 이라 기존에 주소 값에 적어뒀던 "123" 이 무시되고 전화번호 값만 action에 의해서 state에 저장.3) useEffect가 state 변경을 감지하고 validate를 진행후에 reducer의 forceupdate 에 의해 re render 4)주소값이 없었으니 errorr값에 "주소를 입력하세요" 들어있다.라고 이해하면 맞을까요?
-
해결됨실무에 바로 적용하는 프런트엔드 테스트 - 1부. 테스트 기초: 단위・통합 테스트
show more 버튼이 노출되지 않는 테스트 케이스에서 limit 오동작 문제
안녕하세요, 좋은 강의 잘 듣고 있습니다.보여줄 상품 리스트가 없는 경우 show more 버튼이 노출되지 않는다. 테스트 케이스에서 limit 를 20 이하로 입력해도 테스트 실패로 잡히지 않는 문제가 있는 것 같아 보이는데요..!원인을 찾아보려 조금 테스트하다 보니.. render -> screen.findAllByTestId 를 하면서 api가 두 번 호출되는 것 같습니다. 그 과정에서 offset이 limit 만큼 증가해 호출되고 있어요. (즉, 두번째 페이지까지 렌더링했을 때를 기준으로 테스트가 돌아가는 것 같습니다)it('보여줄 상품 리스트가 없는 경우 show more 버튼이 노출되지 않는다.', async () => { await render(<ProductList limit={2} />); // offset : 0 await screen.findAllByTestId('product-card'); // offset : 2 });offset 이 useInfiniteQuery에서 리턴해주는 pageParams로 인해 만들어지는 것 같아서 pageParams가 원인인 것 같긴 한데.. 해결방법을 모르겠네요.혹시 이 부분 수정이 어떻게 되면 좋을지 확인 부탁드립니다..! +)테스트하다가 발견한 건데요, apiRoutes.products 를 mocking하는 handler에서 lastPage로 리턴하는 조건이 잘못된 건 아닌가 해서요..!ctx.json({ products, lastPage: products.length < limit });이면 테스트 코드에서 limit을 10으로 준다고 해도, 두 번째 페이지에서 lastPage가 false인 것 같습니다.ctx.json({ products, lastPage: data.products.length <= offset + limit });으로 수정되어야 하지 않을까 조심스럽게 제안드려 봅니다..!
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
8.6 투두 수정하기) 오류 관련 질문
안녕하세요 선생님 강의 보면서 똑같이 코드를 입력했는데그 이후에 새로고침 하고 체크박스를 누르니까 이런 오류가 발생하네요혹시 무슨 오류인지 알 수 있을까요?