25%
36,300원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
새글추가시 새로생신게시글 id
더미데이터가 id 1부터 id 5까지 총 5개의 게시물이 존재하는데, 새글을 한번 추가하면 그 새글이 id 0으로 추가가 되고, 다시 한번 더 추가시 새글이 id 1로 추가가 됩니다 ㅠㅠ 그래서 새글 추가시 게시글정렬도 꼬이게 보여요ㅠㅠ 왜 이런 오류가 난거지 궁금합니다. 코드샌드박스 주소 첨부합니다!https://codesandbox.io/s/hungry-bogdan-59h25q
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
작성완료 시 onCreate 함수 호출 못함
App.js에서 onCreate함수를 가지고 오지 못하고 있는데 어디서 오류가 났는지 찾지못하고있어요ㅠㅠ! 도와주세요!코드보여드릴게여 ㅠㅠ오류상황Cannot destructure property 'onCreate' of '(0 , react__WEBPACK_IMPORTED_MODULE_0__.useContext)(...)' as it is undefined. TypeError: Cannot destructure property 'onCreate' of '(0 , react__WEBPACK_IMPORTED_MODULE_0__.useContext)(...)' as it is undefined. at DiaryEdit (http://localhost:3000/static/js/bundle.js:344:5) at renderWithHooks (http://localhost:3000/static/js/bundle.js:26416:22) at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:29702:17) at beginWork (http://localhost:3000/static/js/bundle.js:30998:20) at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:16008:18) at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:16052:20) at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:16109:35) at beginWork$1 (http://localhost:3000/static/js/bundle.js:35983:11) at performUnitOfWork (http://localhost:3000/static/js/bundle.js:35230:16) at workLoopSync (http://localhost:3000/static/js/bundle.js:35153:9)App.jsimport React, { useReducer, useRef } from "react"; import "./App.css"; import { BrowserRouter, Routes, Route } 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) => { // return state; 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.targetId ? { ...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: 1687326683094, }, { id: 2, emotion: 2, content: "일기 2번", date: 1687326683096, }, { id: 3, emotion: 3, content: "일기 3번", date: 1687326683097, }, { id: 4, emotion: 4, content: "일기 4번", date: 1687326683098, }, { id: 5, emotion: 5, content: "일기 5번", date: 1687326683099, }, { id: 6, emotion: 3, content: "일기 6번", date: 1787321680269, }, ]; 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, onEdit, onRemove }}> <BrowserRouter> <div className="App"> <Routes> <Route path="/" element={<Home />} /> <Route path="/new" element={<New />} /> <Route path="/edit" element={<Edit />} /> <Route path="/diary/:id" element={<Diary />} /> {/* <Route path="/diary" element={<Diary />} /> */} </Routes> </div> </BrowserRouter> </DiaryDispatchContext.Provider> </DiaryStateContext.Provider> ); } export default App; DiaryEdit.jsimport { useNavigate } from "react-router-dom"; import React, { useState, useRef, useContext } from "react"; import MyHeader from "./MyHeader"; import MyButton from "./MyButton"; import EmotionItem from "./EmotionItem"; import DiaryDispatchContext from "./../App"; // 감정에 대한 데이터 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: "완전 나쁨", }, ]; // 달력에 오늘의 날짜를 기본 날짜로 구현하기 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 DiaryEdit = () => { const contentRef = useRef(); const navigator = useNavigate(); const [date, setDate] = useState(getStringDate(new Date())); // 어떤 감정을 선택했는지 state에 저장 const [emotion, setEmotion] = useState(3); const [content, setContent] = useState(""); const { onCreate } = useContext(DiaryDispatchContext); const handleClickEmotion = (emotion) => { setEmotion(emotion); }; const handleSubmit = () => { if (content.length < 1) { contentRef.current.focus(); return; } onCreate(date, content, emotion); }; return ( <div className="DiaryEdit"> <MyHeader headText={"새로운 일기 쓰기"} leftChild={ <MyButton text={"< 뒤로가기"} onClick={() => navigator(-1)} /> } /> <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 key={it.emotion_id} {...it} onClick={handleClickEmotion} isSelected={it.emotion_id === emotion} /> ))} </div> </section> <section> <h4>오늘의 일기</h4> <div className="input_box text_wrapper"> <textarea placeholder="오늘은 어땠나요?" ref={contentRef} vlaue={content} onChange={(e) => setContent(e.target.value)} /> </div> </section> <section> <div className="control-box"> <MyButton text={"취소하기"} onClick={() => navigator(-1)} /> <MyButton text={"작성완료"} type={"positive"} onClick={handleSubmit} /> </div> </section> </div> </div> ); }; export default DiaryEdit;
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
제가 생각하는 일기 분석 시작이 2번 되는 호출되는 이유가 맞는지 궁금합니다
const getData = async () => { const res = await fetch( "https://jsonplaceholder.typicode.com/comments" ).then((res) => res.json()); const initData = res.slice(0, 20).map((it) => { return { author: it.email, content: it.body, emotion: Math.floor(Math.random() * 5) + 1, created_date: new Date().getTime(), id: dataId.current++, }; }); setData(initData); }; useEffect(() => { getData(); }, []); const getDiaryAnalysis = useMemo(() => { console.log("일기분석"); | 처음 App 컴포넌트 실행이 되었을 때 useEffect를 통해 getData는 데이터를 불러오고 있는 상태이고(비동기가 맞을까요?) getDiaryAnalysis가 실행되면서 처음 "일기분석" 실행되고getData에서 데이터를 불러 온 상태가 되면 useEffect가 mount되면서 App컴포넌트가 한번 더 실행되는게 맞을까요?
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
props 질문 있습니다.
const OddEvenResult = ({ count }) => { return <div>{count % 2 === 0 ? "짝수" : "홀수"}</div>; }; export default OddEvenResult; const OddEvenResult = (count ) => { return <div>{count % 2 === 0 ? "짝수" : "홀수"}</div>; }; export default OddEvenResult; count를 props로 넘겼을 때 첫번째는 제대로 동작하지만 2번째는 짝수,홀수 구분을 하지 못합니다. 하지만 2번째도 count가인건 인지하고 있습니다(홀수로 출력되기 때문) counter.js에서 initalvaue가 객체이기 떄문에 oddevenresult에서도 {} 이렇게 받아야 제대로 동작 하는걸까요?
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
vscode formatting
vscode에서 저장시 foramting을 어떻게 해야할까요?const EmotionItem = ({ emotion_id, emotion_img, emotion_description, onClick }) 저는 저장을 해도 이렇게 한줄로 계속 남습니다.
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
비동기를 동기로 처리하는 이유
비동기 함수를 왜 굳이 동기처럼 실행시키기 위해 await을 사용하는 건가요?처음부터 함수를 만들때 동기로 만들면 되는거 아닌가요?동기, 비동기가 잘이해가 안가네요..
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
함수 동작 원리가 궁금합니다.
function checkmood(mood, goodCallback, bacCallback) { if (mood === "good") { goodCallback(); } else { bacCallback(); } } checkmood("good", sing, cry); function sing() { console.log("sing"); } function cry() { console.log("cry"); } checkmood("good", sing, cry) 이 부분에서 sing이 함수이지만 값으로 들어갔는데, 함수 인자는 값으로만 들어가는걸까요?!
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
방향성에 대한 강의
마지막 멘트하실 때 앞으로 뭘 더 공부하고 어떻게 공부하면 좋을지 알려주신다고 하셨는데 그것에 대한 강의는 없는 건가요? 완강했습니다! 감사합니다~
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
마지막날을 가져올 때 getMonth에 +1을 하는 이유
23번째 줄에서 해당 월의 마지막날을 가져올 때 getMonth에 +1을 하는 이유가 무엇인가요? getMonth에 +1을 하면 이미 그 다음 월로 넘어가는 것 아닌가요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
App.css에서 display:flex를 두 번 적용하는 이유
header에서 이미 display:flex를 적용했는데 header > div에서까지 display:flex를 하는 이유가 무엇인가요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
onClick
해당 부분 22번째 줄에서 onClick에서 navigate함수를 호출할 때 arrow function이 아니라 그냥 navigate("/home") 함수를 호출하였더니 QS 바꾸기 버튼을 눌렀을 때 페이지가 그냥 뒤로 갔습니다. 왜 그런 것인가요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
콜백함수
16번째 줄에서 setSearchParams를 중괄호로 감싸지 않는 이유가 혹시 실행하려는 statement가 하나라서 그런 건가요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
inline css
혹시 4번째 줄에서 inline css style을 적용할 때 {} 중괄호로 한번 더 감싸는 이유가 무엇인가요?
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
DiaryItem
import { useState, useRef } from "react"; const DiaryItem = ({ author, emotion, created_time, content, id, onDelete, onEdit, }) => { const [isEdit, setIsEdit] = useState(false); const [localContent, setLocalContent] = useState(content); // 본문 수정 시 수정 전 콘텐츠 띄우기 const localContentInput = useRef(); const toggleIsEdit = () => { setIsEdit(!isEdit); }; const handleDelete = () => { if (window.confirm(`${id}번째 일기를 삭제하시겠습니까?`)) { onDelete(id); } }; const handleQuitEdit = () => { setIsEdit(false); setLocalContent(content); }; const handleEdit = () => { if (localContent.length < 5) { localContentInput.current.focus(); return; } onEdit(id, localContent); }; return ( <div className="DiaryItem"> <div className="info"> <span> 작성자 : {author} | 감정점수 : {emotion} </span> <br /> <span className="date">{new Date(created_time).toLocaleString()}</span> </div> <div className="content"> {/* 수정 중 콘텐츠 vs 수정 전 콘텐츠 */} {isEdit ? ( <textArea ref={localContentInput} value={localContent} onChange={(e) => setLocalContent(e.target.value)} /> ) : ( <>{content}</> )} </div> {/* 수정 중 버튼 vs 수정 전 버튼 */} {isEdit ? ( <> <button onClick={handleQuitEdit}>수정 취소</button> <button onClick={handleEdit}>수정 완료</button> </> ) : ( <> <button onClick={handleDelete}>삭제하기</button> <button onClick={toggleIsEdit}>수정하기</button> </> )} </div> ); }; export default DiaryItem;위는 제가 수업을 보며 따라친 DiaryItem.js인데 실행을 시키면 수정하기 버튼을 눌렀을 때 원래 콘텐츠가 textArea에 뜨지 않고 수정이 되지 않습니다. 하지만 소스코드에 올려진 DiaryItem.js를 복붙했을 때는 또 됩니다. 몇 번이나 두 파일을 비교했지만 잘못된 점을 찾아낼 수가 없었는데 도와주세요 ㅠㅠ
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
삼항연산자
34번째 줄에서 {content}를 빈 태그로 감싸는 이유가 뭔가요? 어차피 content는 문자열 아닌가요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
defaultProps
Counter.js의 defaultProps를 설정했는데도 count 값이 0으로 설정되지 않아 질문드립니다.각각 App.js랑 Counter.js 입니다.// import logo from './logo.svg'; // import "./App.css"; // inline 스타일 적용 시 필요 없음 import MyHeader from "./MyHeader"; import MyFooter from "./MyFooter"; import Counter from "./Counter"; function App() { let name = "김학준"; const style = { App: { backgroundColor: "black", // Camel case }, h2: { color: "red", }, bold_text: { color: "green", }, }; const counterProps = { a: 1, b: 2, }; return ( // <div className="App"> // <div style={style.App}> <div> <MyHeader /> <Counter {...counterProps} /> {/* <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> */} {/* <h2>안녕 리액트 {name}</h2> */} {/* <h2 style={style.h2}>안녕 리액트 {name}</h2> */} {/* <b id="bold_text">React.js</b> */} {/* <b style={style.bold_text}>React.js</b> */} {/* <MyFooter /> */} </div> ); } export default App; import React, { useState } from "react"; // React의 메소드 const Counter = ({ initialValue }) => { // console.log("counter 호출!"); console.log(initialValue); const [count, setCount] = useState(initialValue); const onIncrease = () => { setCount(count + 1); }; const onDecrease = () => { setCount(count - 1); }; return ( <div> <h2>{count}</h2> <button onClick={onIncrease}>+</button> <button onClick={onDecrease}>-</button> </div> ); }; Counter.defaultProps = { initialValue: 0, }; export default Counter;
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
useState
9번째 줄에서 useState(0)이라는 값이 배열을 반환하는 것이죠?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
inline 스타일 적용
inline 스타일을 적용할 때 div의 속성 className을 제거하는 이유가 무엇인가요?
- 미해결[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
npx
강의에서 설치돼 있지 않은 패키지를 딱 한번만 쓰고 싶을 때 npx를 사용한다고 했는데 이게 무슨 말씀인지 좀 더 자세하게 설명해주실 수 있나요?
- 해결됨[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
Promise의 resolve
왼쪽이 어떻게 오른쪽과 같을 수 있나요? resolve가 콜백함수라서 그런 건가요? 맞다면 좀 더 자세하게 설명해주세요.