묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Next + React Query로 SNS 서비스 만들기
SSR prefetchQuery를 사용하는데 왜 UserInfo에서 데이터를 한번 더 가져오는지 모르겠습니다,,,
안녕하세요! 강의 수강 중 헷갈리는 게 있어 질문 드립니다!!다름이아니라, 강의 초반에 프로필 페이지가 SSR인 것과 prefetchQuery를 사용하는 것에 이해를 했는데, 왜 하위 컴포넌트인 UserInfo에서 다시 userQuery를 통해 데이터를 가져오는지 모르겠습니다!서버사이드 환경인 page.tsx에서 데이터를 가져오기 위해 PrefetchQuery를 사용하는 것으로 알고있는데, 그렇다면 UserInfo에서 useQuery를 통해 데이터를 가져오는 것이 아닌 데이터를 props로 넘겨줄 수 있는게 아닌가 싶습니다!혹시 최상위 page에서 prefetchQuery를 통해 데이터를 먼저 가져와야 그 하위 컴포넌트들 내부의 클라이언트 컴포넌트에서 useQuery를 통해 데이터를 가져올 수 있는건가요?그렇다면 prefetchQuery없이 클라이언트 컴포넌트에서 userQuery만 사용해도 되나요?
-
해결됨한 입 크기로 잘라먹는 Next.js(v15)
SSR로 구현 시 스켈레톤 UI를 적용하지 않아도 될까요?
메인화면에서 SSR로 데이터를 받아오도록 구현한 상태입니다. (page router)데이터가 많아서인지 페이지 접속 시 빈 화면이 출력되는데,스켈레톤 UI를 적용해봐도 스켈레톤 UI가 표시되지 않습니다.스켈레톤 UI는 CSR 환경에서만 사용할 수 있는 걸까요?이런 경우에는 데이터를 CSR로 받아오고, 스켈레톤 UI를 적용하는 게 나을까요?
-
미해결파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 (장고 4.2 기준)
중단점에 대한 질문 있습니다.
실습과장에서 중단점을 클릭 했고 디버그 했는데 중단점에서 멈추지 않고 텍스트 찍어준다면 어떤 문제가 있는 것 일까요. 구글링 해도 정확한 해답을 찾지 못해 이렇게 질문을 남기게 되었습니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
새강의 쿠폰 발급 관련 질문
저도 이전에 미리 구매해놓고 공부하려는데 뒤늦게 확인했습니다.리뉴얼된 버전으로 공부하고 싶은데, 쿠폰을 발급받을 수 있을까요?
-
미해결처음 만난 리액트(React)
버튼이 안 뜹니다
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요 안녕하세요 버튼이 안 떠서 질문드립니다 오타는 없는 것 같은데 버튼이 안 나오네요
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
체크박스 관련 질문
import './App.css' import Header from './components/Header'; import Editor from './components/Editor'; import { useState, useRef,useReducer } from 'react'; import List from './components/List'; const mockData=[ { id:0, isDone: false, content : "React 공부하기", date: new Date().getTime(), }, { id:1, isDone: false, content : "빨래하기", date: new Date().getTime(), }, { id:2, isDone: false, content : "노래 연습하기", date: new Date().getTime(), }, ]; function reducer(state,action){ switch(action.type){ case 'CREATE': return [action.data, ...state]; case 'UPDATE': return state.map((item)=>item.id===action.targetId?{...item, isDone: !item.isDone}:item); case "DELETE": return state.filter((item)=>item.id !==action.targetId); default: return state; } } function App() { // const [todos,setTodos]=useState(mockData); const [todos,dispatch]=useReducer(reducer,mockData); const idRef=useRef(3); const onCreate=(content)=>{ dispatch({ type:"CREATE", data:{ id:idRef.cureent ++, isDone:false, content: content, date: new Date().getTime(), }, }); }; const onUpdate=(targetId)=>{ dispatch({ type:"UPDATE", targetId:targetId }) }; const onDelete=(targetId)=>{ dispatch({ type:"DELETE", targetId:targetId }); }; return ( <div className="App"> <Header /> <Editor onCreate={onCreate} /> <List todos={todos} onUpdate={onUpdate} onDelete={onDelete} /> </div> ); } export default App 강의 10.2를 보던 중 '123'을 리스트에 추가하고 체크박스를 누르는 과정에서 체크박스와 삭제 버튼이 작동하지 않습니다. 기존에 있던 리스트들은 체크와 삭제가 다 되는데 추가된 리스트에 대해서만 작동하지 않는데 틀린 부분이 있는지 궁금합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 '완벽한' 프론트엔드 코스
09-02 graphql 에러
수정페이지에서 수정하기 버튼을 누르면 네트웨크에 이런 에러가 떠요미리보기{ "errors": [ { "message": "Unknown type \"Sting\". Did you mean \"String\" or \"Int\"?", "locations": [ { "line": 1, "column": 67 } ], "extensions": { "code": "GRAPHQL_VALIDATION_FAILED", "exception": { "stacktrace": [ "GraphQLError: Unknown type \"Sting\". Did you mean \"String\" or \"Int\"?", " at Object.NamedType (/frontend-api-example/node_modules/graphql/validation/rules/KnownTypeNamesRule.js:57:29)", " at Object.enter (/frontend-api-example/node_modules/graphql/language/visitor.js:323:29)", " at Object.enter (/frontend-api-example/node_modules/graphql/utilities/TypeInfo.js:370:25)", " at visit (/frontend-api-example/node_modules/graphql/language/visitor.js:243:26)", " at Object.validate (/frontend-api-example/node_modules/graphql/validation/validate.js:69:24)", " at validate (/frontend-api-example/node_modules/apollo-server-core/src/requestPipeline.ts:536:14)", " at Object.<anonymous> (/frontend-api-example/node_modules/apollo-server-core/src/requestPipeline.ts:302:32)", " at Generator.next (<anonymous>)", " at fulfilled (/frontend-api-example/node_modules/apollo-server-core/dist/requestPipeline.js:5:58)", " at processTicksAndRejections (node:internal/process/task_queues:105:5)" ] } } } ]}페이로드 09-03-boards/ [number] 페이지 코드 입니다"use client"; //상세 import { useParams } from "next/navigation"; import { gql, useQuery } from "@apollo/client"; import Link from "next/link"; const FETCH_BOARD = gql` query fetchBoard($mynumber: Int) { fetchBoard(number: $mynumber) { number writer title contents } } `; export default function BoardsDetailPage() { const params = useParams(); //useQuery는 중괄호, uesMutation은 대괄호 const { data } = useQuery(FETCH_BOARD, { variables: { mynumber: Number(params.number) }, }); console.log(data); return ( <div> <div> {Number(params.number)}번 게시글 상세페이지 이동이 완료되었습니다. </div> <div>작성자: {data?.fetchBoard?.writer}</div> <div>제목: {data?.fetchBoard?.title}</div> <div>내용: {data?.fetchBoard?.contents}</div> <Link href={`/section09/09-03-boards/${params.number}/edit`}> 수정하러가기 </Link> </div> ); } 09-03-boards-write 코드 입니다"use client"; import { useMutation, gql } from "@apollo/client"; import { useState } from "react"; import { useParams, useRouter } from "next/navigation"; const 나의그래프큐엘셋팅 = gql` # 타입적는곳 mutation createBoard( $mywriter: String $mytitle: String $mycontents: String ) { # 전달할 변수 적는 곳 createBoard(writer: $mywriter, title: $mytitle, contents: $mycontents) { _id number message } } `; //수정 const UPDATE_BOARD = gql` mutation updateBoard( $mynumber: Int $mywriter: String $mytitle: Sting $mycontents: String ) { updateBoard( number: $mynumber writer: $mywriter title: $mytitle contents: $mycontents ) { _id number message } } `; export default function BoardsWrite(props) { const router = useRouter(); const params = useParams(); console.log(params.number); const [writer, setWriter] = useState(""); const [title, setTitle] = useState(""); const [contents, setContents] = useState(""); const [나의함수] = useMutation(나의그래프큐엘셋팅); //수정 const [updateBoard] = useMutation(UPDATE_BOARD); //등록 const onClickSubmit = async () => { //여기서 그래프큐엘 요청하기 const result = await 나의함수({ //variables 이게 $역할을 함 variables: { mywriter: writer, mytitle: title, mycontents: contents, }, }); console.log(result); alert("등록이 완료되었습니다."); router.push(`/section09/09-03-boards/${result.data.createBoard.number}`); }; //수정 const onClickUpdate = async () => { //여기서 수정하기 하자!! const result = await updateBoard({ variables: { mynumber: Number(params.number), mywriter: writer, mytitle: title, mycontents: contents, }, }); console.log(result); alert("수정이 완료되었습니다."); router.push(`/section09/09-03-boards/${result.data.updateBoard.number}`); }; const onChangeWriter = (event) => { setWriter(event.target.value); }; const onChangeTitle = (event) => { setTitle(event.target.value); }; const onChangeContents = (event) => { setContents(event.target.value); }; return ( <div> 작성자: <input type="text" onChange={onChangeWriter} /> <br /> 제목: <input type="text" onChange={onChangeTitle} /> <br /> 내용: <input type="text" onChange={onChangeContents} /> <br /> <button onClick={props.isEdit ? onClickUpdate : onClickSubmit}> {props.isEdit ? "수정" : "등록"}하기 </button> </div> ); }
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
타입에러가 계속생기는데
타입 포함된 버전을 설치한 후에도 타입에러가 계속 생기는데버전이슈일까요.."dependencies": { "@ant-design/icons": "^5.5.2", "@apollo/client": "^3.11.9", "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "antd": "^5.21.6", "axios": "^1.7.7", "graphql": "^16.9.0", "lodash": "^4.17.21", "next": "12.1.0", "react": "17.0.2", "react-daum-postcode": "^3.2.0", "react-dom": "17.0.2", "react-infinite-scroller": "^1.2.6", "ts-node": "^10.9.2" }, "devDependencies": { "@eslint/js": "^9.18.0", "@graphql-codegen/cli": "^5.0.3", "@graphql-codegen/typescript": "^4.1.2", "@types/node": "17.0.2", "@types/react": "17.0.2", "@types/react-infinite-scroller": "^1.2.5", "eslint": "^9.18.0", "eslint-config-next": "15.1.4", "eslint-config-prettier": "^10.0.1", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.4", "globals": "^15.14.0", "prettier": "^3.4.2", "typescript": "^5.7.3", "typescript-eslint": "^8.20.0""react-infinite-scroller": "^1.2.6", 이고"@types/react-infinite-scroller": "^1.2.5", 로 되어있습니다.++ return ( <div style={{ height: '700px', overflow: 'auto' }}> <InfiniteScroll pageStart={0} loadMore={onLoadMore} hasMore={hasMorePosts} loader={ <div className='loader' key='loader'> Loading... </div> } useWindow={false} > {data?.fetchBoards?.map((el) => el ? ( <div key={el._id}> <span style={{ margin: '10px' }}>{el.title}</span> <span style={{ margin: '10px' }}>{el.writer}</span> </div> ) : null, ) ?? []} </InfiniteScroll> </div> );1. InfiniteScroll 'InfiniteScroll' cannot be used as a JSX component. Its instance type 'InfiniteScroll' is not a valid JSX element. Property 'refs' is missing in type 'InfiniteScroll' but required in type 'ElementClass' 3. loader Type 'Element' is not assignable to type ReactElement<unknown, string | JSXElementConstructor<any>> Types of property 'key' are incompatible. TYpe 'Key | null' is not assignable to type 'string | null'. Type 'number' is not assignable to type 'string'. 4. {data?.~</div>;})} Type 'void[] | undefined' is not assignable to type 'ReactNode'.2. {data?.~</div>;})}Type 'void[] | undefined' is not assignable to type 'ReactNode'. (이하 생략)이런 에러였었는데,상단에 타입선언 해주고 모두 해결 되었습니다.import React, { ReactElement } from 'react'; declare module 'react-infinite-scroller' { interface InfiniteScrollProps { pageStart?: number; loadMore: () => void; hasMore?: boolean; loader?: ReactElement | null; useWindow?: boolean; children?: React.ReactNode; } export default function InfiniteScroll(props: InfiniteScrollProps): ReactElement; }모듈이 덜 설치된건지 ㅠㅠ 왜 이런 에러가 생긴지 모르겠네요 ㅠㅠ
-
미해결따라하며 배우는 리액트 네이티브 기초
오류 잡기
import { Pressable, StyleSheet, Text, View } from 'react-native' import React from 'react' import CheckboxUnChecked from '../assets/checkbox-unchecked.svg'; import CheckboxChecked from '../assets/checkbox-checked.svg'; import DeleteIcon from '../assets/delete.svg'; const TodoItem = () => { return ( <View style={styles.itemContainer}> <Pressable hitSlop={10} style={styles.itemTextChecked} > <CheckboxUnChecked /> <CheckboxChecked style={styles.itemCheckboxCheckedIcon}/> </Pressable> <Text style={[styles.itemText, styles.itemTextChecked]} > 코딩하기 </Text> <Pressable style={[ styles.deleteButton, styles.deleteButtonDone ]} hitSlop={10} > <DeleteIcon /> </Pressable> <Text>TodoItem</Text> </View> ) } export default TodoItem const styles = StyleSheet.create({}) 내가 보낸 이미지 보면 글자가 짤려 왜그런거야? 선생님이 하란대로 했고 14.1로 인스톨해서 에러도 안났어. 그런데 인스톨 하고나서 보니까 글자가 잘리더라고 왜그런거같아?import { SafeAreaView, StyleSheet, Text, View } from 'react-native' import React from 'react' import { StatusBar } from 'expo-status-bar' import { Platform } from 'react-native'; import InputForm from '../components/InputForm' // 대소문자 정확히 일치 import TodoItem from '../components/TodoItem'; const MainScreen = () => { return ( <SafeAreaView style={styles.container}> <StatusBar backgroundColor={'default'} /> <Text style={styles.pageTitle}>ToDo App</Text> <View style={styles.listView}> <Text style={styles.listTitle}>할일</Text> <TodoItem /> </View> <View style={styles.separator} /> <View style={styles.listView}> <Text style={styles.listTitle}>완료된 일</Text> </View> <InputForm/> </SafeAreaView> ) } export default MainScreen const styles = StyleSheet.create({ container: { flex: 1, paddingTop: Platform.OS === 'android' ? 20 : 0, backgroundColor: '#f7f8fa' }, pageTitle: { marginBottom: 35, paddingHorizontal: 15, fontSize: 54, fontWeight: '600' }, separator:{ marginHorizontal: 10, marginTop : 25, marginBottom : 10, borderBottomWidth: 1, borderBottomColor: 'rgba(0,0,0,0.2)', }, listView: { flex: 1, }, listTitle: { marginBottom: 25, paddingHorizontal: 15, fontSize: 41, fontWeight: '500' } })이게 mainscreen이야. 알려줄수있어??
-
미해결따라하며 배우는 리액트 네이티브 기초
강의에서 InputForm.js에서
pressable 자동으로 import되는데 어떻게 하는건가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
강의 관련 질문드립니다.
24년 12월에 결제하여 수강 중입니다올해 [코드캠프] 부트캠프에서 만든 '완벽한' 프론트엔드 코스 강의가 오픈 된 것을 보았는데, 강의 간 내용에 많은 차이 점이 있을까요? 신규 강의를 수강하려면 재결제 하는 방법밖에 없을까요..?
-
해결됨[코드캠프] 부트캠프에서 만든 '완벽한' 프론트엔드 코스
동적페이지 로드밸런서 연결
AWS HTTPS 적용하는 부분에서과정대로 2번 따라했는데똑같이 해당 에러가 나서 https로 접속이 안 되네요 ㅜㅜ이유가 먼지 알 수 있을까요?!
-
미해결파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 (장고 4.2 기준)
todo / react 붙이는 깃주소를 받고 싶습니다.
안녕하세요.수강생입니다.이부분을 5번은 넘게 들은거 같은데 어려워요.깃주소주신것도 가서 봤는데구조도 잘 이해가 안되고todo 와 react만 연동되는 코드를 따로 깃에 주시면 안될까요?todo따로 react따로 폴더를 만들어주신거 같은데myreact01-cra 온전히 todo를 리엑트에 붙이는 깃주소를 따로 만들어주셨으면해서요.전부 한군데에 있어서 분석해보면서 하고는 있는데 저위의 3개의 카테고리중에2개만이라도 되고 싶은데다 합해서 20분수업도 안되는데 전 2분도 못쫓아가고 있어요.리엑트도 어느정도안다고 생각하고장고도 어느정도 안다고 생각하는데도어렵습니다. 흑....소스코드를 받고 싶습니다.인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
섹션3. 스프링부트와 API서버에서 부트 프로젝트 생성 및 확인 강의에 관한 겁니다.
해당 강의 1:51에서 갑자기 데이터베이스 익스플로러용 데이터그립 툴이 나오는데 이에 대한 설정은 어느 강의에서 확인할 수 있는 거죠? 느닷없이 나와서 혼동스럽기만 하네요. 섹션 1의 MariaDB와 부트 프로젝트생성에서도 하이디sql 툴 설정만 하셔서 데이터그립 툴은 어디에서 나온 건지 모르겠습니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
새 강의 쿠폰 관련 문의드립니다
안녕하세요! 비슷한 유형의 질문글을 보고 늦었지만 문의드리게 되었습니다. 공지를 늦게 확인하여 쿠폰을 받지 못했는데 혹시 지금이라도 발급이 가능할까요?
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
vsCode 저장 시 코드 정렬? 에 관한 질문
코드를 치고 control + s를 눌렀을 때 <button> 내부의 요소들이 정환님의 화면처럼 코드들이 세로 일렬로 되도록 세팅하고 싶은데 저는 가로 일렬로 배치가 돼요. 혹시 이 부분 세팅은 어떻게 하는지 알려주실 수 있으실까요?
-
해결됨Next.js 시작하기
EsLint flat config format 으로 만들어질 때 참고
import { dirname } from "path"; import { fileURLToPath } from "url"; import { FlatCompat } from "@eslint/eslintrc"; import prettierPlugin from "eslint-plugin-prettier"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const compat = new FlatCompat({ baseDirectory: __dirname, }); const eslintConfig = [ ...compat.extends("next/core-web-vitals"), ...compat.extends("plugin:prettier/recommended"), { files: ["**/*.js", "**/*.jsx"], plugins: { prettier: prettierPlugin, }, rules: { "no-undef": "error", "prettier/prettier": [ "error", { singleQuote: true, semi: true, tabWidth: 2, trailingComma: "all", printWidth: 80, bracketSpacing: true, arrowParens: "avoid", }, ], }, }, ]; export default eslintConfig;
-
미해결React 완벽 마스터: 기초 개념부터 린캔버스 프로젝트까지
빨간 밑줄 질문이요..
위와 같이 해당 변수나 값을 선언한거를 사용하지 않으면 이렇게 빨간 밑줄이 생기는데요. 이거 없앨수 없나요? 거슬리네요..ㅠ
-
미해결파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 (장고 4.2 기준)
NoReverseMatch at /hottrack/archives/2023/
NoReverseMatch 자체가 되돌아갈 곳이 없다는 오류인 것은 알겠으나,왜 song_archive_year를 못찾는지 모르겠습니다. Viewclass SongYearArchiveView(YearArchiveView): model=Song date_field="release_date" # make_object_list = Trueurls.pyurlpatterns = [ ... path(route="archives/<int:year>/", view=views.SongYearArchiveView.as_view(), name="song_archive_year"), ] --- 혹시나 해서 View를 다음과 같이 했는데class SongYearArchiveView(YearArchiveView): model = Song date_field = "release_date" # 조회할 날짜 필드 make_object_list = True def get_queryset(self): year = self.kwargs['year'] # URL에서 'year' 값을 가져옴 return Song.objects.filter(release_date__year=year) 인지는 하는 것 같아요. 그런데 버튼은 없군요.
-
해결됨한 입 크기로 잘라먹는 Next.js(v15)
book/[id] 과 같은 동적경로에 대응하는 페이지가 어떻게 풀라우트캐시가 동작할 수 있죠?
선생님 강의 5-3) 9분 10초를 보다가 궁금한 것이 있습니다~generateStaticParams으로 지정했던 id값이 아닌4번페이지에 접속했을 때 해당 페이지가 실시간으로 다이나믹하게 페이지가 생성되고 풀라우트캐시에 저장된다고 하셨는데요 풀라우트캐시는 static페이지에서만 동작한다고 알고 있고, [id]컴포넌트에서 fetch함수에 캐싱 옵션으로 'force-cache'을 설정한 것도 아닌데 어떻게 풀라우트 캐시가 동작할 수 있나요??