묻고 답해요
130만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
크롬 개발자 도구 레이아웃 배치 질문
강의 내용과 조금 떨어진 질문입니다. 크롬 개발자 툴에 컴포넌트를 보여주는것과 프롭스,훅스 등을 보여주는 창이 가로로 나뉘어져 보여지고 있는데, 이걸 윈터루드님처럼 위아래로 나뉘어지게 하려면 어떻게 해야하나요?
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
윈터루드님~! 이미지 경로에 관해서 질문 드리겠습니다!!
안녕하세요! img src 주소 관련 질문드리겠습니다! process.env.PUBLIC_URL + `/... 경로`를 하셨는데 src에 그냥 /assets/emotion1.png를 해도 잘 나오는데 상관없는거죠??
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
key 값 할당에 대해 궁금합니다.
강의에서는 useRef 를 사용하면 된다고 하셨는데, 그 이유가 무엇인지에 대한 설명이 없으셔서 let 이나 var 는 불가능한가 해서 테스트해보니 값이 증가하지 않더라구요. 왜 그런지 이유가 궁금합니다. // const dataId = useRef(0); let dataId = 0; const onCreate = (author, content, emotion) => { const created_date = new Date().getTime(); const newItem = { author, content, emotion, created_date, id: dataId, }; dataId += 1; setData([newItem, ...data]); };
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
안녕하세요.. 질문 몇가지 드립니다!
강의 너무 잘듣고 있습니다! 하지만 Props 정말 알듯 모를듯 아리송하네요.. 질문드립니다! 1. 파일명은 무조건 대문자 시작인가요?? 2. 각 컴퍼넌트에 return 뒤에는 하나 이상일 경우 ()가 오고 한 줄 일경우에는 <> </>로도 가능할까요? 3. children 이라는 Props는 고정된 이름인가요? 다른 child같은걸로는 변경 불가능하죠?? 변경해서 하니까 오류가 나더라구요! 4. <button count={count}> 이렇게 속성으로 준 Props와 객체로 선언해서 넘겨주는 Props를 동시에 사용 못하나요?? const Counter = (props,{ counterValue3 }) => { const [count, setCount] = useState(counterValue3); // props 매개변수로 받아 프로퍼티로 전달 방법 이런식으로 말이죠..
-
미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
Mount가 두번 실행되는건 왜 그럴까요?
강의 잘 보고 있습니다. 질문이 있는데요, useEffect()로 Mount 를 구현하였고, 콘솔에 로그를 Mount를 출력하였습니다. 그런데, 이상하게, Mount 로그가 두번씩 출력됩니다. 동작은 이상없지만, 두번 출력되는게 이상해서요~ 제가 무엇을 잘못했는지 궁금합니다. useEffect(()=>{ console.log("Mouint!"); }, []); 즐거운 하루 보내세요.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
Uncaught Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>
react-redux에서 발생하는 오류인듯 한데 구글링 해보니 수업 코드와 너무 달라지는데 어떻게 해결해야 할까요? 코드일부 import { useDispatch } from 'react-redux'; import {loginUser} from '../../../_actions/user_action'; function LoginPage() { const dispatch = useDispatch(); 깃:https://github.com/kim-seungmin/boiler_plate
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
useEffect mount 문의
안녕하세요. 강사님, 강의 잘 듣고 있습니다. 다름이 아니라, useEffect 부분 따라하고 있는데 다르게 작성한 부분이 없는데 useEffect 부분이 항상 2번씩 호출되서 콘솔에 찍힙니다. 다른 예제 할때도 이게 계속 반복되는데 혹시 왜 그런걸 까요?
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
개발자 도구 에러메세지 표기 화면 문의
안녕하세요. 이제 막 React를 시작한 초보 개발자 입니다. 강의 11분에 리스트를 undefined 했을때 어떤 부분에서 에러가 나는지 강사님과 같은 화면을 보고싶으면 어떻게 해야하나요? 저는 위와 같은 화면이 뜨지 않고 빈 화면만 표기가 됩니다. 그리고 콘솔에 에러 표기도 DiaryList.js 가 아닌 bundle.js 로 표기가 되는데ㅠ 강사님처럼 상세 에러 화면을 보려면 어떻게 해야 하나요? 궁금합니다!
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
디폴트 프롭스 관련 부분 질문드립니다.
안녕하세요. 강의 잘 보고 있습니다. 다름 아니라 defaultProps 부분과 관련해서 여쭤보고 싶은 게 있어서요. 지금 강의에서는 props가 undefined으로 올 때 등을 대비해서 defaultProps을 지정해주시는데, 혹시 이 방법 말고 diaryList에 바로 디폴트 값(빈 배열)을 할당하면 안 될까요? (ex. {diaryList = []}) => {...} ) 기본값 매개 변수로 지정할 수도 있을 것 같아서 여쭤봅니다. 아니면 혹시 차이점이 있을까요? 감사합니다!
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onCreate emotion undefined 문의
안녕하세요. 강의 보면서 기초 개념 다지는 중인 학생입니다 :) 다름이 아니라 일기 작성 시 제목과 내용 본문 입력 후, 점수를 별도로 선택하여(이벤트 발생) 저장하면 데이터가 잘 넘어가는데, default로 설정한 점수에서 점수를 별도로 선택하지 않고 제목과 내용만 입력 후 저장하면 데이터가 넘어가지 않은 채 undefined로 콘솔에 확인이 됩니다.ㅠㅠ 간략하게는 제목, 내용, 점수 모두 지정해서 저장하면 잘 나옴. A 제목, 내용만 쓰고 디폴트 점수로 저장하면 점수가 undefined로 됨. 입니다! B 어디가 문제인지 하루종일 들여다봐도 문제를 찾을 수가 없어서 질문드려요ㅠㅠ
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
"더미데이터와 포스트폼 만들기" 강의순서 관련 코드 작성 뒤, 로그인에서 게시판으로 넘어가지 않는 문제로 질문 드립니다!
안녕하세요. 제로초님의 강의에 큰 도움을 받고 있음에 감사의 말씀을 드립니다. 여러 검색결과도, 질문답변도, 해당강의 반복재생으로 찾아보았으나 해결치 못한 부분이 있어 이렇게 직접 질문을 하게 됐네요! [ 마주한 문제점 & 상황 ] 은 다음과 같습니다. 1. (이전상황) 로그인폼(Id, Pwd)에 텍스트를 입력해 "로그인" 버튼을 누르면 정상적으로 로그인이 됐고, Redux 역시 정상작동해 개발자도구에서 확인이 가능했습니다. 2. (현재상황) 섹션3(Redux) "더미데이터와 포스트폼 만들기" 강의를 들으며 문제에 마주했습니다. 3. (더미데이터와 포스트폼 만들기 강의 후) 잘 넘어가던 로그인 화면에서 데이터는 넘어가 콘솔에 찍히지만, 화면 페이지는 게시판으로 넘어가지 않는 상황에 직면했습니다. [ 콘솔에 찍히는 Error ] 는 다음과 같습니다. [정상적으로 넘어가는 로그인 데이터] -> 그러나 로그인이 되지 않고 화면이 넘어가질 않습니다! [ 소스코드 ] 1. package.json { "name": "react-nodebird-front", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "next -p 3060", "build": "next build" }, "author": "jj", "license": "ISC", "dependencies": { "@ant-design/icons": "^4.7.0", "antd": "^4.19.0", "next": "^9.5.5", "next-redux-wrapper": "^6.0.2", "prop-types": "^15.8.1", "react": "^16.14.0", "react-dom": "^16.14.0", "react-redux": "^7.2.8", "redux": "^4.1.2", "redux-devtools-extension": "^2.13.9", "styled-components": "^5.3.3" }, "devDependencies": { "eslint": "^8.10.0", "eslint-plugin-hooks": "^0.4.2", "eslint-plugin-import": "^2.25.4", "eslint-plugin-react": "^7.29.3" } } 2. LoginForm.js 파일 import React, { useState, useCallback, useMemo } from 'react'; import { Form, Input, Button } from 'antd'; import Link from 'next/link'; import styled from 'styled-components'; import { useDispatch, useSelector } from 'react-redux'; import useInput from "../hooks/useInput"; import { loginAction } from '../reducers/user'; const ButtonWrapper = styled.div ` margin-top: 10px; `; const FormWrapper = styled(Form) ` padding: 10px; `; const LoginForm = ({ setIsLoggedIn }) => { const dispatch = useDispatch(); const [id, onChangeId] = useInput(''); const [password, onChangePassword] = useInput(''); const onSubmitForm = useCallback(() => { console.log(id, password); dispatch(loginAction({id, password})); }, [id, password]); return ( <FormWrapper onFinish={onSubmitForm}> <div> <label htmlFor="user-id">아이디</label> <br /> <Input name="user-id" value={id} onChange={onChangeId} required /> </div> <div> <label htmlFor="user-password">비밀번호</label> <br /> <Input name="user-password" type="password" value={password} onChange={onChangePassword} required /> </div> <ButtonWrapper> <Button type="primary" htmlType="submit" loading={false}>로그인</Button> <Link href="/signup"><a><Button>회원가입</Button></a></Link> </ButtonWrapper> </FormWrapper> ); } export default LoginForm; 3. index.js import React from 'react'; import { useSelector } from "react-redux"; import AppLayout from "../components/AppLayout"; import PostForm from '../components/PostForm'; import PostCard from '../components/PostCard'; const Home = () => { const { isLoggedIn } = useSelector((state) => state.user); const { mainPosts } = useSelector((state) => state.post); return ( <AppLayout> {isLoggedIn && <PostForm /> } {mainPosts.map((post) => <PostCard key={post.id} post={post} />)} </AppLayout> ); } export default Home; 4. configureStore.js import { createWrapper } from 'next-redux-wrapper'; import { applyMiddleware, compose, createStore } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension'; import reducer from '../reducers'; const configureStore = () => { const middlewares = []; const enhancer = process.env.NODE_ENV === 'production' ? compose(applyMiddleware(...middlewares)) : composeWithDevTools(applyMiddleware(...middlewares)); const store = createStore(reducer, enhancer); return store; }; const wrapper = createWrapper(configureStore, { debug: process.env.NODE_ENV === 'development', }); export default wrapper; 5. post.js // [ initialState ] export const initialState = { mainPosts: [{ id: 1, User: { id: 1, nickname: 'jj', }, content: '첫 번째 게시글 #해시태그 #익스프레스', Images: [{ src: 'https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAxNjExMjFfMjM2%2FMDAxNDc5NjY5MjEyOTEz.13R8uiaA0T8rJnLPJICAib4oVtrAzA424jbDMC9a3ckg.m0QoHt-5MdR0MH501npcL8aJof3Eu1h_9Zp0ceNm8e4g.PNG.guri4you%2F%25BB%25F6%25B1%25F2_%25BD%25C9%25B8%25AE%25C5%25D7%25BD%25BA%25C6%25AE1.png&type=sc960_832', }, { src: 'https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAxNjExMjFfMjM2%2FMDAxNDc5NjY5MjEyOTEz.13R8uiaA0T8rJnLPJICAib4oVtrAzA424jbDMC9a3ckg.m0QoHt-5MdR0MH501npcL8aJof3Eu1h_9Zp0ceNm8e4g.PNG.guri4you%2F%25BB%25F6%25B1%25F2_%25BD%25C9%25B8%25AE%25C5%25D7%25BD%25BA%25C6%25AE1.png&type=sc960_832', }, { src: 'https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAxNjExMjFfMjM2%2FMDAxNDc5NjY5MjEyOTEz.13R8uiaA0T8rJnLPJICAib4oVtrAzA424jbDMC9a3ckg.m0QoHt-5MdR0MH501npcL8aJof3Eu1h_9Zp0ceNm8e4g.PNG.guri4you%2F%25BB%25F6%25B1%25F2_%25BD%25C9%25B8%25AE%25C5%25D7%25BD%25BA%25C6%25AE1.png&type=sc960_832', }], Comments: [{ User: { nickname: 'jj4', }, content: 'redux를 학습 중입니다.', }, { User: { nickname: 'jj3', }, content: '다음은 sage를 학습 예정임.', }] }], imagePaths: [], postAdded: false, } const ADD_POST = 'ADD_POST'; export const addPost = { type: ADD_POST, } const dummyPost = { id: 2, content: '더미데이터입니다.', User: { id: 1, nickname: 'jj1', }, Images: [], Comments: [], }; const reducer = (state = initialState, action) => { switch (action.type) { case ADD_POST: return { ...state, mainPosts: [dummyPost, ...state.mainPosts], postAdded: true, }; default: return state; } }; export default reducer; 6. PostForm.js import React, { useCallback, useState, useRef } from 'react'; import { Form, Input, Button } from 'antd'; import { useSelector, useDispatch } from 'react-redux'; import { addPost } from '../reducers/post'; const PostForm = () => { const { imagePaths } = useSelector((state) => state.post); const dispatch = useDispatch(); const imageInput = useRef(); const [text, setText] = useState(''); const onChangeText = useCallback((e) => { setText(e.target.value); }, []); const onSubmit = useCallback(() => { dispatch(addPost); setText(''); }, []); const onClickImageUpload = useCallback(() => { imageInput.current.click(); }, [imageInput.current]); return ( <Form style={{ margin: '10px 0 20px' }} encType="multipart/form-data" onFinish={onSubmit}> <Input.TextArea value={text} onChange={onChangeText} maxLength={140} placeholder="어떤 신기한 일이 있었나요?" /> <div> <input type="file" multiple hidden ref={imageInput}/> <Button onClick={onClickImageUpload}>이미지 업로드</Button> <Button type="primary" style={{ float: 'right' }} htmlFor="submit">짹짹</Button> </div> <div> {imagePaths.map((v) => ( <div key={v} style={{ display: 'inline-block'}}> <img src={v} style={{ width: '200px' }} alt={v} /> <div> <Button>제거</Button> </div> </div> ))} </div> </Form> ) }; export default PostForm; 7. PostCard.js import React from 'react'; const PostCard = () => { return ( <div> PostCard </div> ); }; export default PostCard; 8. user.js import { HYDRATE } from 'next-redux-wrapper'; // initialState 부분 const initialState = { user: { isLoggedIn: false, user: null, signUpData: {}, loginData: {}, }, post: { mainPosts: [], } }; // [로그인] action creator export const loginAction = (data) => { return { type: 'LOG_IN', data, } }; // [로그아웃] action creator export const logoutAction = (data) => { return { type: 'LOG_OUT', } }; // reducer const rootReducer = (state = initialState, action) => { switch (action.type) { case HYDRATE: console.log('HYDRATE', action); return { ...state, ...action.payload }; case 'LOG_IN': return { ...state, user: { ...state.user, isLoggedIn: true, user: action.data, }, }; case 'LOG_OUT': return { ...state, user: { ...state.user, isLoggedIn: false, user: null, }, }; default: return state; } }; export default rootReducer; 다소 많은 양의 글 내용이지만, 시간이 허락되실 때 답변 주시면, 참 감사할 것 같습니다! 오늘 하루도 고생많으셨고, 이번 한 주도 파이팅입니다! 늘 양질의 강의 감사합니다 ^^
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onCreate 이후 property 의 undefind 에러
add 후에 List페이지로 이동하면, 흰화면으로 에러가 출력됩니다.Home.js 의 프로퍼티에 대해 undefind 가 출력됩니다.[Uncaught TypeError: Cannot read properties of undefined (reading 'length') at Home.js:15:1] [ diaryList.length >= 1 ] : 에러 발생하는 부분 useEffect(() => { if (diaryList.length >= 1) { //에러발생부분 const firstDay = new Date( curDate.getFullYear(), curDate.getMonth(), 1 ).getTime(); const lastDay = new Date( curDate.getFullYear(), curDate.getMonth() + 1, 0 ).getTime(); setData( diaryList.filter((it) => firstDay <= it.date && it.date <= lastDay) ); } }, [diaryList, curDate]);
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
JS 객체 강의에서 메모리에 관해 질문 드립니다.
강의 15분 대에 객체 프로퍼티 속성을 delete하면 결국 삭제가 된 상태이고, 브라우저에서는 더이상 콘솔 로그를 찍어도 알 수가 없습니다. 그러나 왜 여전히 메모리가 삭제 되지 않았는지 그 의미가 이해되지 않아 질문을 드립니다.
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
copyList
안녕하세요 강의 듣는 중 궁금한점이 생겨서 질문을 드리게 됩니다. 영상 24:32 부분에서 const copyList = JSON.parse(JSON.stringify(diaryList));으로 하셧는데 원본 배열을 정렬을 하게되어 불변성 문제 때문에 Json.stringify 로 문자열로 바꿧다가 다시 JSON.parse로 새로운 배열을 만들어 값을 받았는데 혹시 그럼 스프레드 연산자인 const copyList = [...diaryList] 이렇게 하게 된다면 위 코드와 다르게 동작이 될까요..?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
클라이언트에서 db를 가져오려면
안녕하세요 선생님 유익한 강의 잘 수강하고있습니다. 현재 회원가입까지 구현이 다 되어서 몽고 db에 회원가입시 데이터가 잘 들어가는것도 확인하였고, 클라이언트(프론트) 상에서 이 db를 가져와서 쓰고싶은데 어떻게 해야 가져와서 쓸수있을까요? 프론트만 파서 이쪽은 잘 감이 안잡힙니다 감사합니다.
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
JSX에 대한 질문드립니다.
안녕하세요. JSX에서 문법규칙에서 반드시 부모 요소 하나가 감싸는 형태여야 한다라고 하는데 부모 요소가 무엇인지 알수 있을까요?
-
해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
DiaryEditor 페이지 date가 이상하게 받아져요
신규글을 등록할 때에도 제일 밑으로가지고, 기존 글을 수정해도 밑으로 가지길래 Components로 확인해보니 date값이 다르게 들어가져요.. 더미데이터로 넣은 date는 1648092529386 ~ 90 인데 새로운글이나 수정글은 date가 1648080000000 로 나오네요ㅠㅠ onCreate랑 OnEdit이 DiaryEditor.js에서 date를 가져가기에 console.log(new Date(date).getTime()); DiaryEditor.js 안에서 onCreate,onEdit 안에서 쓰는 getTime으로 찍어보면 1648080000000 나오는데 어디서 꼬인걸까요 ...? ㅠ https://codesandbox.io/s/sharp-brown-p38cvp?file=/src/components/DiaryEditor.js
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
postman에서 전송했을 때 무한 로딩이 해결이 안됩니다. 다른분들 방식도 안됩니다
안녕하세요. 강의 잘 보고 있습니다 제가 토큰 생성까지 따라했는데 무한로딩이 발생했습니다. if(err) return cb(err);로 수정을 했는데도 계속 로딩이 발생하네요 save함수 안에서는 console.log도 안찍히는 거 봐선 save함수가 문제인거 같기도 한데 검색해도 아무 정보도 안나와서 정말 답답하네요.. 혹시 도와주실수 있을까 해서 git hub 주소 올려봅니다 https://github.com/ChyoPyoRo/CP1
-
미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
톡방 비밀번호
지금까지 강의 보면서 톡방 비번을 못본거 같은데 혹시 어디에 있었는지 알 수 있을까요..
-
미해결파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트
npm install 로 문제없이 yarn 설치를 했는데 yarn 이 실행이 안되네요
- 혹시 위와같은 문제에 대해서 알수 있을까요