25%
36,300원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onChange 작동 원리
좋은 강의 감사합니다.페이지 구현 - 홈 )/) 강의 중 23분에 onchange 설명해주신 것 관련해서 질문드립니다.DiaryList.js / 27번째 줄에 onChange로 setSortType을 전달했기 때문에 ControllMenu에서 onChange(e.target.value)의 값이 setSortType을 호출해서 sortType의 상태값이 변화하는 것으로 이해했습니다.즉 이렇게, onChange{setSortType("변화된 값")} 작동한걸로 이해했는데요. 27번째 줄에 onChange = {setSortType} 으로만 작성을 했는데 e.target.value라는 값이 전달된 것이 이해가 잘 안되어서 질문드립니다.만일 setSortType처럼 상태값을 받는 함수를 담고 있는 변수가 아닌const test = (a,b) => { console.log(a,b);}와 같은 매개변수를 2개를 받는 함수를 onchange로 호출한다고 하면 어떻게 넣을 수 있나요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
비동기 방식에서 콜백함수 사용 이유
강의 10분 경 비동기 방식에서 코드 실행 결과를 확인하기 위해 콜백함수를 사용해야 한다고 하셨는데, 아래와 같이 예시를 들어주신 콜백함수를 사용하는 코드와 그렇지 않는 코드의 다른 점이 무엇인지 궁금합니다. 두 코드의 결과는 똑같이 -1 -> 12 -> 7 순서로 콘솔창에 출력됩니다.첫 번째는 예시를 들어주신 코드이고, 두 번째는 왜 콜백함수를 써서 결과를 봐야하지??라는 궁금증으로 수정해본 코드입니다. function taskA(a, b, cb) { setTimeout(() => { const res = a + b; cb(res); }, 3000); } function taskB(a, b, cb) { setTimeout(() => { const res = a * b; cb(res); }, 2000); } function taskC(a, b, cb) { setTimeout(() => { const res = a - b; cb(res); }, 1000); } taskA(3, 4, (res) => { console.log(res); }); taskB(3, 4, (res) => { console.log(res); }); taskC(3, 4, (res) => { console.log(res); }); taskA1(); // 이후 실행 console.log("코드 끝"); // taskA1 를 기다리지 않고 // 먼저 실행function taskA(a, b) { setTimeout(() => { const res = a + b; console.log(res); }, 3000); } function taskB(a, b) { setTimeout(() => { const res = a * b; console.log(res); }, 2000); } function taskC(a, b) { setTimeout(() => { const res = a - b; console.log(res); }, 1000); } taskA(3, 4); taskB(3, 4); taskC(3, 4);
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onEdit setData 없어도 되는건가요?
안녕하세요 강사님!강의를 따라가는 도중 제가 onEdit 함수에 setData를 하지 않았다는 사실을 알게 되었습니다.하지만 setData를 해주지 않고 data에 map 함수로 변경 해주는 동작만 해도 정상적으로 수행되는데 왜 그런지 알 수 있을까요?useCallback 해주기 전에도 정상 동작한 이유도 궁금하고 강사님께서 알려주신 대로 data에는 컴포넌트가 마운트 됐을때 data 상태인 빈 배열이 들어가 있어야 하는 것이 아닌가요?아래는 제가 짠 onEdit 함수 입니다const editDiary = useCallback((targetId, editedContent) => { data.map((e) => e.id === targetId ? {...e, content: editedContent} : e ) }, [])
- 미해결[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로 나올까요? ㅠㅠ