25%
36,300원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
일기 추가 시 DiaryEditor 리렌더링 질문
안녕하세요 강사님강의를 듣고 저는 React.memo로 DiaryEditor를 고차 컴포넌트를 만들어 동일한 prop을 받았을 때 리렌더링 되지 않도록 해주고 onCreate 함수를 useCallback을 통해 메모리제이션 하여 같은 함수를 DiaryEditor에 prop으로 전달한다고 이해했습니다그래서 제가 생각했을 땐 일기를 새로 저장하거나, 삭제, 수정하는 작업 중에는 DiaryEditor가 아예 리렌더링이 되지 않아야 된다고 생각했는데 강의 14분 17초에서도 그렇고 제가 직접 짠 코드에서도 일기를 새로 저장할 때 리렌더링이 되는데 제가 이해한게 잘못 된건가 싶어 질문 드립니다!
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
async return 자료형이 Promise인 설징에 대한 질문
async로 선언된 함수의 반환형은 promise아닌가요? console.log(res)가 문자열 hello async를 출력하는 이유를 모르겠습니다.
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
id..???
DiaryItem의 버튼에있는 onClick에서 사용되는 id는 props로 받아온 걸 사용하는건가요? 🚨 아래의 가이드라인을 꼭 읽고 질문을 올려주시기 바랍니다 🚨질문 하시기 전에 꼭 확인해주세요- 질문 전 구글에 먼저 검색해보세요 (답변을 기다리는 시간을 아낄 수 있습니다)- 코드에 오타가 없는지 면밀히 체크해보세요 (Date와 Data를 많이 헷갈리십니다)- 이전에 올린 질문에 달린 답변들에 꼭 반응해주세요 (질문에 대한 답변만 받으시고 쌩 가시면 속상해요 😢)질문 하실때 꼭 확인하세요- 제목만 보고도 무슨 문제가 있는지 대충 알 수 있도록 자세한 제목을 정해주세요 (단순 단어 X)- 질문의 배경정보를 제공해주세요 (이 문제가 언제 어떻게 발생했고 어디까지 시도해보셨는지)- 문제를 재현하도록 코드샌드박스나 깃허브 링크로 전달해주세요 (프로젝트 코드에서 문제가 발생할 경우)- 답변이 달렸다면 꼭 확인하고 반응을 남겨주세요- 강의의 몇 분 몇 초 관련 질문인지 알려주세요!- 서로 예의를 지키며 존중하는 문화를 만들어가요. - 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
컴포넌트 잘 만드는 법
안녕하세요!! 컴포넌트를 잘 만드는 법 이런게 있을까요? 조금 난해합니다ㅜ 기준이 사람마다 다른건 알지만 하나라도 알고싶네요! - 이전에 올린 질문에 달린 답변들에 꼭 반응해주세요 (질문에 대한 답변만 받으시고 쌩 가시면 속상해요 😢)질문 하실때 꼭 확인하세요- 제목만 보고도 무슨 문제가 있는지 대충 알 수 있도록 자세한 제목을 정해주세요 (단순 단어 X)- 질문의 배경정보를 제공해주세요 (이 문제가 언제 어떻게 발생했고 어디까지 시도해보셨는지)- 문제를 재현하도록 코드샌드박스나 깃허브 링크로 전달해주세요 (프로젝트 코드에서 문제가 발생할 경우)- 답변이 달렸다면 꼭 확인하고 반응을 남겨주세요- 강의의 몇 분 몇 초 관련 질문인지 알려주세요!- 서로 예의를 지키며 존중하는 문화를 만들어가요. - 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
setstate 함수를 props로 전달했을 때 자식 컴포넌트의 리렌더링을 막을 수 있다고 이해하는 게 맞을까요?
섹션6 '프로젝트 최적화' 강의의 14:30부터 끝 부분까지의 내용 관련 궁금한 점이 있어 질문 드립니다!강의를 들으면서, setstate 함수는 자동으로 useCallback 처리가 되어 반환되는 함수라 생각하면 되고, 따라서 setstate 함수를 props로 전달하면 성능 최적화를 할 수 있다고 이해했는데요,그래서 DiaryEditor 컴포넌트가 자식 컴포넌트인 EmotionItem 에게 onClick={handleClickEmote} 를 props로 전달할 때 onClick={(e) => setEmotion(e)} 와 같이 setEmotion이라는 상태변화 함수를 전달해주면 useCallback을 사용하지 않고도 최적화를 할 수 있을 거라고 생각했습니다!그러나 확인해보니 이 코드로는 최적화가 되지 않는데, 이유가 무엇인지 이해가 잘 되지 않습니다 ㅠㅠ(EmotionItem에 React.memo로 묶어주었습니다!)혹시 제가 잘못 이해한 부분이 있는지 여쭤봐도 괜찮을까요? 아래는 DiaryEditor.js 코드입니다!import { useState, useRef, useContext, useEffect, useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { DiaryDispatchContext } from './../App'; import EmotionItem from './EmotionItem'; import MyHeader from './MyHeader'; import MyButton from './MyButton'; import { getStringDate } from '../util/data'; import { emotionList } from '../util/emotion'; const DiaryEditor = ({ isEdit, originData }) => { const contentRef = useRef(); const [content, setContent] = useState(''); const [emotion, setEmotion] = useState(3); const [date, setDate] = useState(getStringDate(new Date())); const navigate = useNavigate(); const { onCreate, onEdit, onRemove } = useContext(DiaryDispatchContext); const handleClickEmote = useCallback((emotion) => { setEmotion(emotion); }, []); const handleSubmit = () => { if (content.length < 1) { contentRef.current.focus(); return; } if ( window.confirm( isEdit ? '일기를 수정하시겠습니까?' : '새로운 일기를 작성하시겠습니까?' ) ) { if (!isEdit) { onCreate(date, content, emotion); } else { onEdit(originData.id, date, content, emotion); } } navigate('/', { replace: true }); }; const handleRemove = () => { if (window.confirm('정말 삭제하시겠습니까?')) { onRemove(originData.id); navigate('/', { replace: true }); } }; useEffect(() => { if (isEdit) { setDate(getStringDate(new Date(parseInt(originData.date)))); setEmotion(originData.emotion); setContent(originData.content); } }, [isEdit, originData]); return ( <div className='DiaryEditor'> <MyHeader headerText={isEdit ? '일기 수정하기' : '새 일기 쓰기'} leftChild={ <MyButton onClick={() => navigate(-1)} text={'< 뒤로가기'} /> } rightChild={ isEdit && ( <MyButton onClick={handleRemove} text={'삭제하기'} type={'negative'} /> ) } /> <div> <section> <h4>오늘은 언제인가요?</h4> <div className='input_box'> <input className='input_date' value={date} onChange={(e) => setDate(e.target.value)} type='date' /> </div> </section> <section> <h4>오늘의 감정</h4> <div className='input_box emotion_list_wrapper'> {emotionList.map((it) => ( <EmotionItem onClick={handleClickEmote} isSelected={it.emotion_id === emotion} key={it.emotion_id} {...it} /> ))} </div> </section> <section> <h4>오늘의 일기</h4> <div className='input_box text_wrapper'> <textarea ref={contentRef} value={content} onChange={(e) => setContent(e.target.value)} placeholder='오늘은 어땠나요?' ></textarea> </div> </section> <section> <div className='control_box'> <MyButton text={'취소하기'} onClick={() => navigate(-1)} /> <MyButton text={'작성완료'} type={'positive'} onClick={handleSubmit} /> </div> </section> </div> </div> ); }; export default DiaryEditor;
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
v18로 해도 상관 없을까요?
코드샌드 박스 보니까 선생님께서는 v17로 사용하고 계시는 것 같은데, 버전은 맞추는게 좋을까요?
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
렌더 시 bebel dependencies 오류 메세지 발생
안녕하세요. 강의 잘 보고 있습니다. :)다름이 아니라 run start 시 아래와 같은 문구가 뜨고 있어 질문 드립니다.One of your dependencies, babel-preset-react-app, is importing the "@babel/plugin-proposal-private-property-in-object" package without declaring it in its dependencies. This is currently working because "@babel/plugin-proposal-private-property-in-object" is already in your node_modules folder for unrelated reasons, but it may break at any time. babel-preset-react-app is part of the create-react-app project, which is not maintianed anymore. It is thus unlikely that this bug will ever be fixed. Add "@babel/plugin-proposal-private-property-in-object" to your devDependencies to work around this error. This will make this message go away. 구글링을 해서 아래 코드를 추가하면 된다고 하여 일단 해결은 하였는데요.npm install --save-dev @babel/plugin-proposal-private-property-in-object 저의 지식으로는 이런 이슈가 왜 발생했고 단순히 저 코드를 추가함으로서 어떻게 해결되었는지 잘 이해가 되지 않아 강의 내용과는 무관하나 여쭤봅니다. 이런 오류를 몇 번 봤었는데 매번 이렇게 코드를 입력해야 하는지 혹시 강사님 께서는 오류 발생 원인과 해결 방법을 아실까요? 감사합니다.
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
vite + react로 학습중인데
.
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
content부분 초기화가 되지않아 질문 남깁니다!
안녕하세요 강사님 :)강의 수강 중, author, emotion부분은 저장 이후 초기화가 되나, content부분은 초기화가 되지 않습니다! 🥲 아무리 오타 있나...확인을 해보고 ㅠ_ㅠ..어떤 오류가 있는건지 찾아아도 더 이상 모르겠어서 글을 남깁니다! 샌드박스 포크(?) 주소를 함께 남겨요. 감사합니다! https://codesandbox.io/s/chapt-2-forked-dc3sm8
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
Props 접근 방식 질문
안녕하세요. 섹션5 4번째 강의를 수강하면서 궁금한 게 생겨 질문글 남김니다.강의 영상 7:02 쯤에서 App.js에서 정의한 dummyList를 하위의 컴포넌트인 DiaryList에서 받아올 때 ({diaryList}) => {...}라고 객체를 직접적으로 명시해서 전달하는 방법을 확인하였습니다. 그런데 이 방식말고도 const DiaryList = (props) => {..} 이렇게 전달받아서 함수 내에서 props.diaryList로 리스트에 접근하는 것도 가능하다는 것을 알게 되었습니다.하위 컴포넌트에서 (props.전달인자명)으로 접근하는 것과 ({전달인자명})으로 접근하는 것의 차이가 있는 지 궁금합니다.
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
React 실전프로젝트 질문
왜 강의와 다르게 이렇게 표시되는게 맞는지 굼금해서 올려봅니다.아니라면 왜 이런지 알려주시면 감사하겠습니다.밑에는 App.css입니다.@import url('https://fonts.googleapis.com/css2?family=Nanum+Pen+Script&family=Yeon+Sung&display=swap'); body { background-color: #f6f6f6; display: flex; justify-content: center; align-items: center; font-family: 'Nanum Pen Script'; min-height: 100vh; margin: 0px; } @media (min-width: 650px) { .App { width: 640px; } } @media (max-width: 650px) { .APP { width: 90vw; } } #root { background-color: white; box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px; } .App { min-width: 100vh; padding-left: 20px; padding-left: 20px; } /* my button */ .MyButton { cursor: pointer; border: none; border-radius: 5px; padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 20px; font-size: 18px; white-space: nowrap; font-family: 'Nanum Pen Script'; } .MyButton_default { background-color: #ececec; color: black; } .MyButton_positive { background-color: #64c964; color: white; } .MyButton_negative { background-color: #fd565f; color: white; } /* header */ header { padding-top: 20px; padding-bottom: 20px; display: flex; align-items: center; border-bottom: 1px solid #e2e2e2; } header > div { display: flex; } header .head_text { width: 50%; font-size: 25px; justify-content: center; } header .head_btn_left { width: 25%; justify-content: start; } header .head_btn_right { width: 25%; border-left: 25px; justify-content: end; } header button { font-family: 'Nanum Pen Script'; } /* DiaryList */ .DiaryList .menu_wrapper { margin-top: 20px; margin-bottom: 30px; display: flex; justify-content: space-between; } .DiaryList .menu_wrapper .right_col { flex-grow: 1; } .DiaryList .menu_wrapper .right_col button { width: 100%; } .DiaryList .ControlMenu { margin-right: 10px; border: none; border-radius: 5px; background-color: #ececec; padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 20px; cursor: pointer; font-family: 'Nanum Pen Script'; font-size: 18px; } /* DiaryItem */ .DiaryItem { padding-top: 15px; padding-bottom: 15px; border-bottom: 1px solid #e2e2e2; display: flex; justify-content: space-between; } .DiaryItem .emotion_img_wrapper { cursor: pointer; min-width: 120px; height: 80px; border-radius: 5px; display: flex; justify-content: center; } .DiaryItem .emotion_img_wrapper_1 { background-color: #64c964; } .DiaryItem .emotion_img_wrapper_2 { background-color: #9dd772; } .DiaryItem .emotion_img_wrapper_3 { background-color: #fdce17; } .DiaryItem .emotion_img_wrapper_4 { background-color: #fd8446; } .DiaryItem .emotion_img_wrapper_5 { background-color: #fd565f; } .DiaryItem .emotion_img_wrapper img { width: 50%; } .DiaryItem .info_wrapper { flex-grow: 1; margin-left: 20px; cursor: pointer; } .DiaryItem .diary_date { font-weight: bold; font-size: 25px; margin-bottom: 5px; } .DiaryItem .diary_centent_preview { font-size: 18px; } .DiaryItem .btn_wrapper { min-width: 70px; } /* DirayEditor */ .DirayEditor textarea { font-family: 'Nanum Pen Script'; font-size: 20px; box-sizing: border-box; width: 100%; min-height: 200px; resize: vertical; border: none; border-radius: 5px; background-color: #ececec; padding: 20px; } .DirayEditor .control_box { display: flex; justify-content: space-between; align-items: center; } .DirayEditor section { margin-bottom: 40px; } .DirayEditor h4 { font-size: 22px; font-weight: bold; } .DirayEditor .input_date { border: none; border-radius: 5px; background-color: #ececec; padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 20px; cursor: pointer; font-family: 'Nanum Pen Script'; font-size: 20px; } .DirayEditor .emotion_list_wrapper { display: grid; grid-template-columns: repeat(5, auto); gap: 2%; } /* EmotionItem */ .EmotionItem { cursor: pointer; border-radius: 5px; padding-top: 20px; padding-bottom: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center; } .EmotionItem img { width: 50%; margin-bottom: 10px; } .EmotionItem span { font-size: 18px; } .EmotionItem_off { background-color: #ececec; } .EmotionItem_on_1 { background-color: #64c964; color: white; } .EmotionItem_on_2 { background-color: #9dd772; color: white; } .EmotionItem_on_3 { background-color: #fdce17; color: white; } .EmotionItem_on_4 { background-color: #fd8446; color: white; } .EmotionItem_on_5 { background-color: #fd565f; color: white; }
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
context api 사용시 ( ) 안에
createContext( ) 괄호 안에 데이터를 입력하면 어디에 쓰이나요?value에 기본값으로 해당 데이터가 들어 가는건가요?예를 들어 export const DiaryStateContext = React.createContext("HELLO"); 이런 식이면 저 HELLO를 어디서 꺼내서 쓸수 있을까요? const hello = useContext(DiaryStateContext);이런 식으로 해도 데이터가 들어 오는거 같진 않네요 ㅜㅜ
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onClick 사용시 질문입니다!
onClick를 이용할경우 onClick= { ( ) => ?? } 해당 형식으로 사용해야하는 경우가 있고 아닌경우가 있는데 헷갈리네요 ㅜㅜ 클릭할떄 실행되는함수가 파라미터를 받지않는다면 onClick={함수명} 이런식이고 파라미터를 받는다면 onClick={( )=>함수명( 파라미터 )} 이런식인거같은데 다른경우도 있을까요?? 콜백 함수에 관한 영상을 찾아보면 이해가 될까요??
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
dummyData 받아오는 오류가 있습니다.
페이지 구현- 홈(/) 파트에서 17:00분 정도에 useEffect를 사용하여 data를 콘솔에 찍어보는데 그전까지는 home component까지는 더미데이터가 잘 받아와졌는데 저부분에서 콘솔에서 이렇게 빈배열로 넘어와져요계속 코드를 몇번씩이나 강의돌려보고 검토했지만 도저히 제눈엔 보이지않아 강사님께 질문드립니다.깃허브에 코드올려놨습니다. 한번 검토해주시면 감사하겠습니다!!https://github.com/eunsoo-cho/emotion-Diart.git
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
만약에 글이 엄청 많을 때도 filter 사용해서 삭제하는지 궁금합니다.
선생님 안녕하세요!실제 서비스들은 누적된 글개수가 엄청 많은데, 실제 현업에서도 filter로 글삭제를 하는지 궁금합니다.글 개수가 엄청 많아지면 글 하나 삭제버튼 눌렀을 때 filter로 배열을 돌다가 로딩이 느려질 것 같다는 생각이 들어서요!
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
삭제하기 버튼은 왜 없나요?
DiaryEditor에서 뒤로가기랑 취소하기 버튼 2개가 있는데 "취소하기를 삭제하기로 바꿔야 하는 것 아닌가?"라는 의문이 들었습니다. 강의를 모든 페이지 구성까지 들었는데 어디에서 일기 삭제하기가 없어서요..혹시 책이나 뒷 강의에 나올진 모르겠지만..
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
날짜 형식
const getStringDate = (date) => { return date.toISOString().slice(0, 10); } const New = () => { const [date, steDate] = useState(getStringDate(new Date())); const navigate = useNavigate(); return ( <div> <MyHeader headText={"새 일기쓰기"} leftChild={<MyButton text={'< 뒤로 가기'} onClick={()=> navigate(-1)}/>} /> <div> <section> <h4>오늘은 언제인가요?</h4> <div className="input-box"> <input value={date} type="date" onChange={(e) => steDate(e.target.value)} /> </div> </section> </div> </div> ) }왜 저는 yyyy-mm-dd 형식이 아니라 yyyy.mm.dd로 나올까요? ㅠㅠ
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
date 설정을 바꿀 수 없을까요?
date를 나타내기 위해const getStringDate = (date) => { return date.toISOString().slice(0, 10); }사용헤서 date를 설정하니까밤에 작성하건 낮에 작성하건 Home페이지에서모두 같은 시간으로 저장되서 시간순으로 저장되는 느낌이 안사는 것 같아요.toISOstring을 안하고 onCreate에 데이터를 넣는 코드 구조도 알려주실 수 있나요? --------------------------------------스스로 생각을 해보았는데 혹시const handleSubmit = () => { if (content.length < 1) { contentRef.current.focus(); return; } onCreate({ date, content, emotion }); navigate("/", { replace: true }); };에서 onCreate 함수에 date대신 new Date().getTime()를 넣으면 제가 생각한 문제가 해결될까요? --------------------------------------다시 생각을 해보았는데 이렇게 하면 시간이 지났을때 전날 일기를 작성할 수가 없네요..
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
npx create-react-app 오류 문의드립니다
뭐가 문제일까요? ㅠㅠ
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
diaryList 날짜 필터 관련
안녕하세요. 저는 현재 "페이지구현-홈(/)" 강의 18분 쯔음 까지 들었습니다.Home 컴포넌트에서 filter 를 사용하여 현재 날짜에만 dummyList 로 작성해둔 일기가 떠야하는데 뜨질 않습니다.import { DiaryStateContext } from "./App"; import MyButton from "./components/MyButton"; import MyHeader from "./components/MyHeader"; import { useContext, useEffect, useState } from "react"; import DiaryList from "./components/DiaryList"; const Home = () => { const diaryList = useContext(DiaryStateContext); //dummyList 를 받음 const [data,setData] = useState(); const [curDate , setCurDate] = useState(new Date()); const headText= `${curDate.getFullYear()}년 ${curDate.getMonth() + 1}월`; useEffect(()=> { if (diaryList.length >= 1) { const firstDay = new Date( curDate.getFullYear(), curDate.getMonth(), 1 ).getTime(); //현재 년, 월의 1일의 시간을 구함 const lastDay = new Date( curDate.getFullYear(), curDate.getMonth() +1, 0, ).getTime(); setData(diaryList.filter((it) => firstDay <= it.date && it.date <= lastDay)); } },[diaryList, curDate]); useEffect(() => { console.log(data) console.log(diaryList) },[data]) const increaseMonth = () => { setCurDate(new Date( curDate.getFullYear() , curDate.getMonth() + 1, curDate.getDate() )) } const decreaseMonth = () => { setCurDate( new Date(curDate.getFullYear(), curDate.getMonth() - 1, curDate.getDate()) ); }; return ( <div> <MyHeader leftChild={<MyButton text={"<"} onClick={decreaseMonth} />} headText={headText} rightChild={<MyButton text={">"} onClick={increaseMonth} />} /> <DiaryList diaryList={data}/> </div> ); } export default Home;이게 제 Home 컴포넌트이고, 중간에 보면 useEffect 로 data 와 diaryList 를 출력했을때 data 는 빈 배열로 출력되고 diaryList 는 제가 App.js 에서 dummyList 로 작성한 데이터가 잘 출력됩니다. 아무리 봐도 어디가 잘못된건지 모르겠습니다. ㅜㅜ날짜가 잘못된건가 싶어 new Date() 로 다시 확인해봐도 현재 날짜로 잘 나옵니다이건 useEffect 로 출력한 콘솔창 입니다.