25%
36,300원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
diaryList 질문
안녕하세요! 우선 좋은 강의 제공해주셔서 감사해요. 다름이 아니라, 강의 영상 28:47 부분과 같이 다이어리 리스트가 화면에 떠야 하는데 뜨지 않는 에러가 발생했고, 스스로 해결이 안 돼서 도움을 요청하려고 글을 쓰게 되었어요. 개발자도구 요소 탭에서도 리스트가 뜨지 않더라구요. 코드 마지막 부분 즉 export default DiaryList; 바로 앞 부분에 console.log(diaryList);도 입력해 보았는데 콘솔 창에는 undefined라고 출력이 되었어요. 코딩 공부가 처음이다보니 에러를 해결하기 위해 무엇부터 손을 대야 할 지도 모르겠고 질문조차 어떻게 해야 할 지 모르겠네요..ㅎㅎ
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
컴포넌트 구조 질문
안녕하세요. 강의를 잘 듣고 있습니다. 6:49 부모 컴포넌트에서 데이터를 자식 컴포넌트로 이동하는데 만일 자식끼리 데이터를 useState로 해야 한다면 redux를 이용하면 될까요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
안녕하세요 감정일기 글 수정간 slice is not a function 으로 나와서 진도가 막혀있네요 ㅠ slice(0,25)부분에 에러가뜹니다
DiaryItem.js부 import MyButton from "./MyButton"; import {useNavigate} from "react-router-dom"; const DiaryItem = ({ id, emotion, content, date}) => { const env = process.env; env.PUBLIC_URL = env.PUBLIC_URL || ""; const navigate = useNavigate(); const strDate = new Date(parseInt(date)).toLocaleDateString(); const goDetail = ()=>{ navigate(`/diary/${id}`); } const goEdit = ()=>{ navigate(`/edit/${id}`); } return( <div className="DiaryItem"> <div onClick={goDetail} className={[ "emotion_img_wrapper", `emotion_img_wrapper_${emotion}`, ].join(" ")}> <img src={process.env.PUBLIC_URL + `assets/emotion${emotion}.png`}></img> </div> <div onClick={goDetail} className="info_wrapper"> <div className="diary_date">{strDate}</div> <div className="diary_content_preview">{content.slice(0,25)}</div> </div> <div className="btn_wrapper"> <MyButton onClick={goEdit} text={"수정하기"} /> </div> </div> ); }; export default DiaryItem; --------------------------------------------------------------------------------------------------- DiaryEditor.js import {useNavigate} from "react-router-dom"; import {useState,useRef,useContext, useEffect} from "react"; import {DiaryDispatchContext} from "./../App.js"; import MyButton from './MyButton'; import MyHeader from './MyHeader'; import EmotionItem from "./EmotionItem"; export const getStringDate = (date) => { let year = date.getFullYear(); let month = date.getMonth() + 1; let day = date.getDate(); if (month < 10) { month = `0${month}`; } if (day < 10) { day = `0${day}`; } return `${year}-${month}-${day}`; }; const emotionList = [ { emotion_id : 1, emotion_img : process.env.PUBLIC_URL + `/assets/emotion1.png`, emotion_descript:'완전 좋음', }, { emotion_id : 2, emotion_img : process.env.PUBLIC_URL + `/assets/emotion2.png`, emotion_descript:'좋음', }, { emotion_id : 3, emotion_img : process.env.PUBLIC_URL + `/assets/emotion3.png`, emotion_descript:'보통', }, { emotion_id : 4, emotion_img : process.env.PUBLIC_URL + `/assets/emotion4.png`, emotion_descript:'나쁨', }, { emotion_id : 5, emotion_img : process.env.PUBLIC_URL + `/assets/emotion5.png`, emotion_descript:'매우 나쁨', }, ] const DiaryEditor = ({isEdit,originData}) => { const navigate = useNavigate(new Date(getStringDate)); const contentRef = useRef(); const [content,setContent]=useState(""); const [emotion,setEmotion] =useState(3); const [date, setDate] = useState(getStringDate(new Date())); const {onCreate,onEdit} = useContext(DiaryDispatchContext); const handleClickEmotion = (emotion)=>{ setEmotion(emotion); }; const handleSubmit = () => { if(content.length <1){ contentRef.current.focus(); return; } if(window.confirm( isEdit? "일기를 수정하시겠습니까?" :"새로운 일기를 작성하시겠습니까?")){ if(!isEdit) { onCreate(date,content,emotion); } else { console.log(originData); onEdit(originData.id, date, content, emotion); } } 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 headText = {isEdit ? " 일기수정하기 " : " 새 일기쓰기 "} leftChild = { <MyButton text={"< 뒤로가기"} onClick={()=>navigate(-1)}/> } /> <div> <section> <h4>오늘은 언제인가요?</h4> <div className="input_box"></div> <input className="input_date" value={date} onChange ={(e)=>setDate(e.target.value)} type="date" /> </section> <section> <h4>오늘의 감정</h4> <div className="input_box emotion_list_wrapper"> {emotionList.map((it)=> ( <EmotionItem key={it.emotion_id} {...it} onClick={handleClickEmotion} isSelected={it.emotion_id === emotion} /> ))} </div> </section> <section> <h4>오늘의 일기</h4> <textarea placeholder="오늘 하루 어땠어요?" ref={contentRef} value={content} onChange={(e)=>setContent(e.target.value)}/> </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) : 기초부터 실전까지
크롬 개발자 도구 레이아웃 배치 질문
강의 내용과 조금 떨어진 질문입니다. 크롬 개발자 툴에 컴포넌트를 보여주는것과 프롭스,훅스 등을 보여주는 창이 가로로 나뉘어져 보여지고 있는데, 이걸 윈터루드님처럼 위아래로 나뉘어지게 하려면 어떻게 해야하나요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
윈터루드님~! 이미지 경로에 관해서 질문 드리겠습니다!!
안녕하세요! img src 주소 관련 질문드리겠습니다! process.env.PUBLIC_URL + `/... 경로`를 하셨는데 src에 그냥 /assets/emotion1.png를 해도 잘 나오는데 상관없는거죠??
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onCreate 함수 호출에 대해 질문드립니다.
안녕하세요 강사님 강의 잘 듣고 있는 중에 궁금한 부분이 있어서 질문드립니다. 지금은 DiaryEditor.js에서 prop으로 받은 onCreate 함수를 호출할때 인수로 (state.author, state.content, state.emotion) 3 가지를 전달하고 있습니다. 이렇게 객체의 프로퍼티를 각각 함수의 인수로 전달하는 것은 객체의 프로퍼티가 추가되거나 삭제되었을 때 함수의 호출부를 수정해야되니 비효율적이라는 생각이 들었습니다. 그리하여 ES6의 구조분해할당을 이용하여 DiaryEditor.js에서 onCreate 함수를 호출할 때 onCreate(state)로 객체를 전달하고 App.js에서 onCreate 함수의 매개변수 부분을 onCreate({author, content, emotion})으로 수정하였습니다. 이렇게 코드를 수정한다면 문제가 되는 부분이 있는지, 문제가 있다면 그것을 어떻게 해결해야 되는지에 대해 질문드립니다. 감사합니다 :)
- 해결됨[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!"); }, []); 즐거운 하루 보내세요.
- 해결됨[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 어디가 문제인지 하루종일 들여다봐도 문제를 찾을 수가 없어서 질문드려요ㅠㅠ
- 해결됨[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] 이렇게 하게 된다면 위 코드와 다르게 동작이 될까요..?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onCreate is not a function 에러
안녕하세요 이정환 강사님! 강의 정말 잘 듣고 따라서 열심히 만들고 있습니다 다름이 아니라 강사님 강의를 보고 따라서 만들다가 오류를 만났는데 오류 잡기가 너무 어려워서 질문 남겨요. 강의 39분 부터 시작되는 작성완료 부분에서 글을 쓰고 작성완료를 누르면 홈으로 이동은 하는데 글이 등록이 되지 않습니다 제가 작성한 오류 관련 부분 DiaryEditor.js, App.js 코드 남겨드립니다 DiaryEditor.js import { useNavigate } from "react-router-dom"; import { useContext, useRef, useState } from "react"; import { DiaryDispatchContext } from "./../App.js"; import MyHeader from "./MyHeader"; import MyButton from "./MyButton"; import EmotionItem from "./EmotionItem"; const emotionList = [ { emotion_id: 1, emotion_img: process.env.PUBLIC_URL + `/assets/emotion1.png`, emotion_descript: "best", }, { emotion_id: 2, emotion_img: process.env.PUBLIC_URL + `/assets/emotion2.png`, emotion_descript: "good", }, { emotion_id: 3, emotion_img: process.env.PUBLIC_URL + `/assets/emotion3.png`, emotion_descript: "not bad", }, { emotion_id: 4, emotion_img: process.env.PUBLIC_URL + `/assets/emotion4.png`, emotion_descript: "bad", }, { emotion_id: 5, emotion_img: process.env.PUBLIC_URL + `/assets/emotion5.png`, emotion_descript: "worst", }, ]; const getStringDate = (date) => { return date.toISOString().slice(0, 10); }; const DiaryEditor = () => { const contentRef = useRef(); // 오늘의 일기를 state에 mapping 하기 위한 state const [content, setContent] = useState(""); // 어떤 감정을 선택했는지 저장할 state const [emotion, setEmotion] = useState(3); const [date, setDate] = useState(getStringDate(new Date())); const { onCreate } = useContext(DiaryDispatchContext); // emotion을 클릭하면 수행할 함수 const handleClickEmote = (emotion) => { setEmotion(emotion); }; const navigate = useNavigate(); //작성완료 버튼의 기능 const handleSubmit = () => { if (content.length < 1) { contentRef.current.focus(); return; } //context length가 적절한 길이가 되었을때 onCreate 함수를 호출 onCreate(date, content, emotion); navigate("/", { replace: true }); }; return ( <div className="DiaryEditor"> <MyHeader headText={"write a diary"} leftChild={<MyButton text={"< back"} onClick={() => navigate(-1)} />} /> <div> {/* 역할은 div와 동일한데 이름만 다르다 */} <section> <h4>Date</h4> <div className="input_box"> {/* 날자 선택이 가능한 html 태그 */} <input value={date} onChange={(e) => setDate(e.target.value)} className="input_date" type="date" /> </div> </section> <section> <h4>Feeling</h4> <div className="input_box emotion_list_wrapper"> {emotionList.map((it) => ( <EmotionItem key={it.emotion_id} {...it} onClick={handleClickEmote} //emotion감정이 선택된 감정인지 아닌지를 알게하기 위한 prop // 선택된 emotion의 값과 같은 emtion = true, 같지 않은 emotion = false isSelected={it.emotion_id === emotion} /> ))} </div> </section> <section> <div className="input_box text_wrapper"> <textarea placeholder="How was your day?" ref={contentRef} value={content} onChange={(e) => setContent(e.target.value)} ></textarea> </div> </section> <section> <div className="control-box"> <MyButton text={"save"} type={"positive"} onClick={handleSubmit} /> </div> </section> </div> </div> ); }; export default DiaryEditor; App.js import React, { useReducer, useRef } from "react"; import "./App.css"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import Home from "./pages/Home"; import New from "./pages/New"; import Edit from "./pages/Edit"; import Diary from "./pages/Diary"; const reducer = (state, action) => { let newState = []; switch (action.type) { case "INIT": { return action.data; } case "CREATE": { newState = [action.data, ...state]; break; } case "REMOVE": { newState = state.filter((it) => it.id !== action.targetId); break; } case "EDIT": { newState = state.map((it) => it.id === action.data.id ? { ...action.data, } : it ); break; } default: return state; } return newState; }; export const DiaryStateContext = React.createContext(); export const DiaryDispatchContext = React.createContext(); const dummyData = [ { id: 1, emotion: 1, content: "오늘의일기 1번", date: 1648633885549, }, { id: 2, emotion: 2, content: "오늘의일기 2번", date: 1648633885550, }, { id: 3, emotion: 3, content: "오늘의일기 2번", date: 1648633885551, }, { id: 4, emotion: 4, content: "오늘의일기 4번", date: 1648633885552, }, { id: 5, emotion: 5, content: "오늘의일기 5번", date: 1648633885553, }, ]; function App() { const [data, dispatch] = useReducer(reducer, dummyData); console.log(new Date().getTime()); const dataId = useRef(0); const onCreate = (date, content, emotion) => { dispatch({ type: "CREATE", data: { id: dataId.current, date: new Date(date).getTime(), content, emotion, }, }); dataId.current += 1; }; const onRemove = (targetId) => { dispatch({ type: "REMOVE", targetId }); }; const onEdit = (targetId, date, content, emotion) => { dispatch({ type: "EDIT", data: { id: targetId, date: new Date(date).getTime(), content, emotion, }, }); }; return ( <DiaryStateContext.Provider value={data}> <DiaryDispatchContext.Provider value={{ onCreate, onRemove, onEdit }}> <BrowserRouter> <div className="App"> <Routes> <Route path="/" element={<Home />} /> <Route path="/new" element={<New />} /> <Route path="/edit/:id" element={<Edit />} /> <Route path="/diary/:id" element={<Diary />} /> </Routes> </div> </BrowserRouter> </DiaryDispatchContext.Provider> </DiaryStateContext.Provider> ); } export default App;
- 해결됨[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
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
페이지 구현 - 홈
페이지 구현 - 홈 강의에서 개발자메뉴에서 컴포넌트에서 홈에서는 일기5개가 잘 출력되는데 다이어리 리스트 만들기 전에 개발자메뉴 콘솔에서 일기5개가 출력이 안되고 다이어리 리스트로도 일기5개가 출력이 안됩니다 어디를 확인 해야 될까요..