48,400원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
diaryList 를 컴포넌트 porps으로 안내리고 map을 돌린 뒤 값을 prop 하는 이유가 궁금합니다.
<div> {diaryList.map(it => { <DiaryItem key={it.id} {...it} /> })} </div>강의중 궁금한부분이 있습니다. 반복문 map 돌려서 컴포넌트에 값을 주고 있는데요. 왜 컴포넌트에 통째로 diaryList를 props로 내리지 않는지 궁금합니다. 만약 내린다면<DiaryItem itemList={diaryList} />위처럼 내려서 해당 컴포넌트에서 map을 돌리지 않는 이유가 궁금합니다!
- 해결됨한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
[강의 23:38] 비동기 처리 중 console.log() 호출 순서
안녕하세요 정환님, 인프런에 많은 강의를 들어보며 이렇게 만족스러운 강의가 있었나 싶을만큼 좋은 강의 제공해주셔서 감사드립니다. 비동기 처리 과정에 대해 질문드립니다.비동기 처리 결과를 다시 인수로 받아 연이어 사용하는 callback hell을 보여주시면서 실행 순서를 말씀해주셨습니다. 이때 call stack에 쌓이는 function context는 taskA()가 앞서지만 함수의 구현부가 비동기 함수로만 이루어져 WebAPIs에서 대기를 하게되고 이동안 taskA()의 다음 순서인 console.log()가 호출되는걸로 이해하면 될까요? 다시한번 좋은 강의 감사드립니다.
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onRemove 원리 질문
안녕하세요! useReduce를 사용하고 최적화를 한 단계에서 onReduce() 함수가 어떻게 최적화 되는지 원리에 의문이 생겨 질문 드립니다. const [data, dispatch] = useReducer(reducer, []); //reducer 생략 case "REMOVE": return state.filter((it) => it.id !== action.targetId); 해당 코드에서 REMOVE를 실행하면 data 배열이 새로운 배열로 업데이트가 됨 -> 2. 그러면 data를 prop으로 받고 있는 DiaryList.js에서 이를 감지하고 처음부터 끝까지 DiaryItem.js를 다시 생성함. ->3. 그런데 DiaryItem은 React.memo로 prop를 비교하는데, 얕은 비교를 하기에 data에 새로 생성된 배열과는 주소가 달라 새로운 컴포넌트를 다시 생성. 이 되어야 하지 않을까요? 혹시 저의 논리에서 어디 부분이 잘못되었는지 모르겠어서 질문합니다... ㅠ
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
컴포넌트 부모 태그
안녕하세요! 좋은 수업 잘 듣고 있습니다 :)props로 컴포넌트를 받는 Container 컴포넌트에 대해 질문이 있습니다!JSX 규칙 중에 모든 컴포넌트는 부모 태그를 가지고 있어야 한다고 말씀해주셨는데 아래 코드처럼 Container는 부모 태그가 없이도 잘 동작하기에 이유가 무엇인지 궁금합니다!function App() { const counterprops = { a : 1, b : 2, c : 3, d : 4, initialVaule : 5, }; return ( // HTML을 반환 <Container> <div className="App"> <Counter {...counterprops}/> </div> </Container> ); }또한 function App() { const counterprops = { a : 1, b : 2, c : 3, d : 4, initialVaule : 5, }; return ( // HTML을 반환 <div className="App"> <Container> <Counter {...counterprops}/> </Container> </div> ); }이렇게 코드를 짜면 동작하지 않더라구요! 왜 첫번째 코드는 동작하고, 두번째 코드는 동작하지 않는지 궁금합니다!감사합니다.
- 해결됨한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
index.js React 17, React 18 버전 질문
안녕하세요. 강의를 계속 듣다가 App.js가 자꾸 두번 실행되어 index.js를 제외한 모든 코드를 강사님의 sandbox 코드를 복붙하였는데 계속 코드가 두번 실행이 되었습니다.그리하여 이렇게 dataId가 20부터 실행되는 문제가 발생하였는데요, 그래서 index.js를 강사님 버전(React 17)로 바꾸었더니 이 문제가 해결되었습니다. React18버전으로 하면 이런 문제가 발생하는 이유가 무엇인가요?? 다음은 저의 index.js 코드입니다. import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; const rootNode = document.getElementById("root"); ReactDOM.createRoot(rootNode).render( <React.StrictMode> <App /> </React.StrictMode> ); reportWebVitals();
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onDelete관련
안녕하세요 onDelete관련 질문 드립니다. <DiaryList onDelete={onDelete} diaryList={data} />해당 부분에서 onDelete와 {onDelete} 의 역할이 다른 것인지 궁금합니다 두번째 onDelete는 앞서 작성한 함수를 전달한 것으로 이해했는데 앞에 있는 onDelete는 js의 onClick onFocus 처럼 이벤트핸들러인지 단순 설정한 props명 인 것인지 궁금합니다
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
setState관련
20분경 나온 setState관련해서 미리 코드를 짜보았었는데용 <div className="DiaryEditor"> <h2>오늘의 일기</h2> <div> <input value={state.author} onChange={(e) => { setState(e.target.value); }} /> </div> <div> <textarea value={state.content} onChange={(e) => { setState(e.target.value); }} placeholder="내용을 입력해주세요" /> </div> </div> 이렇게 짜도 정상적으로 작동이 되는데 더 깊이 들어가서 문제가 생기는 경우일까요??
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
프로젝트에 사용할 상태와 로직 관리 라이브러리 훅 사용 질문입니다.
로그인 및 인증,인가(세션,jwt둘다 사용), 게시판(이미지포함), 댓글, 소켓채팅 정도의 기능을 구현하여 테스트 코드와 docker로 띄워서 CI/CD까지 구현하려고 합니다.상태랑 로직 관리를 useReducer, React Context API, React Query, redux, graphql 정도로 생각하고 있는데 어떤걸로 하는게 좋을까요?!
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
최적화 useMemo 적용하고 나서, 삭제 를 하였을 경우 나타나는 에러입니다.
기존에 잘 동작되었던 삭제 기능이었는데 useMemo 를 적용하고 나서 삭제버튼을 누르니 삭제가 되지 않고 에러가 뜹니다. ㅠ 개발자도구에서 위 소스가 잘못되었다고 하는것같은데 어느곳을 수정해야하는지 모르겠습니다. ㅠ똑같이 친거같은데 ... 이외에도 혹시 리액트 적용해서 에러가 났을경우, 이 에러만 가지고 어느 부분을 수정해야할지 너무 막막한데, 구글링해도 답도 안나오구요 . 어떤식으로 해결해야좋은지 팁도 부탁드립니다.
- 미해결한입 크기로 잘라 먹는 리액트(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로 호출한다고 하면 어떻게 넣을 수 있나요?
- 해결됨한입 크기로 잘라 먹는 리액트(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);
- 해결됨한입 크기로 잘라 먹는 리액트(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 ) }, [])
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
일기 추가 시 DiaryEditor 리렌더링 질문
안녕하세요 강사님강의를 듣고 저는 React.memo로 DiaryEditor를 고차 컴포넌트를 만들어 동일한 prop을 받았을 때 리렌더링 되지 않도록 해주고 onCreate 함수를 useCallback을 통해 메모리제이션 하여 같은 함수를 DiaryEditor에 prop으로 전달한다고 이해했습니다그래서 제가 생각했을 땐 일기를 새로 저장하거나, 삭제, 수정하는 작업 중에는 DiaryEditor가 아예 리렌더링이 되지 않아야 된다고 생각했는데 강의 14분 17초에서도 그렇고 제가 직접 짠 코드에서도 일기를 새로 저장할 때 리렌더링이 되는데 제가 이해한게 잘못 된건가 싶어 질문 드립니다!
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
async return 자료형이 Promise인 설징에 대한 질문
async로 선언된 함수의 반환형은 promise아닌가요? console.log(res)가 문자열 hello async를 출력하는 이유를 모르겠습니다.
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
id..???
DiaryItem의 버튼에있는 onClick에서 사용되는 id는 props로 받아온 걸 사용하는건가요? 🚨 아래의 가이드라인을 꼭 읽고 질문을 올려주시기 바랍니다 🚨질문 하시기 전에 꼭 확인해주세요- 질문 전 구글에 먼저 검색해보세요 (답변을 기다리는 시간을 아낄 수 있습니다)- 코드에 오타가 없는지 면밀히 체크해보세요 (Date와 Data를 많이 헷갈리십니다)- 이전에 올린 질문에 달린 답변들에 꼭 반응해주세요 (질문에 대한 답변만 받으시고 쌩 가시면 속상해요 😢)질문 하실때 꼭 확인하세요- 제목만 보고도 무슨 문제가 있는지 대충 알 수 있도록 자세한 제목을 정해주세요 (단순 단어 X)- 질문의 배경정보를 제공해주세요 (이 문제가 언제 어떻게 발생했고 어디까지 시도해보셨는지)- 문제를 재현하도록 코드샌드박스나 깃허브 링크로 전달해주세요 (프로젝트 코드에서 문제가 발생할 경우)- 답변이 달렸다면 꼭 확인하고 반응을 남겨주세요- 강의의 몇 분 몇 초 관련 질문인지 알려주세요!- 서로 예의를 지키며 존중하는 문화를 만들어가요. - 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
컴포넌트 잘 만드는 법
안녕하세요!! 컴포넌트를 잘 만드는 법 이런게 있을까요? 조금 난해합니다ㅜ 기준이 사람마다 다른건 알지만 하나라도 알고싶네요! - 이전에 올린 질문에 달린 답변들에 꼭 반응해주세요 (질문에 대한 답변만 받으시고 쌩 가시면 속상해요 😢)질문 하실때 꼭 확인하세요- 제목만 보고도 무슨 문제가 있는지 대충 알 수 있도록 자세한 제목을 정해주세요 (단순 단어 X)- 질문의 배경정보를 제공해주세요 (이 문제가 언제 어떻게 발생했고 어디까지 시도해보셨는지)- 문제를 재현하도록 코드샌드박스나 깃허브 링크로 전달해주세요 (프로젝트 코드에서 문제가 발생할 경우)- 답변이 달렸다면 꼭 확인하고 반응을 남겨주세요- 강의의 몇 분 몇 초 관련 질문인지 알려주세요!- 서로 예의를 지키며 존중하는 문화를 만들어가요. - 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
- 미해결한입 크기로 잘라 먹는 리액트(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;
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
v18로 해도 상관 없을까요?
코드샌드 박스 보니까 선생님께서는 v17로 사용하고 계시는 것 같은데, 버전은 맞추는게 좋을까요?
- 미해결한입 크기로 잘라 먹는 리액트(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 저의 지식으로는 이런 이슈가 왜 발생했고 단순히 저 코드를 추가함으로서 어떻게 해결되었는지 잘 이해가 되지 않아 강의 내용과는 무관하나 여쭤봅니다. 이런 오류를 몇 번 봤었는데 매번 이렇게 코드를 입력해야 하는지 혹시 강사님 께서는 오류 발생 원인과 해결 방법을 아실까요? 감사합니다.
- 미해결한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
vite + react로 학습중인데
dev tools에서 npm run dev를 하면 활성화가 안되고,npm run preview 모드로 봐야만 활성화가 되는데, 코드 수정 후 cli를 또 작성해줘야 하는 번거로움이 있습니당.어떻게 해결하면 좋을까요?