묻고 답해요
158만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
로컬스토리지
import { Route, Routes } from "react-router-dom"; import { useReducer, useRef, createContext, useEffect, useState } from "react"; import Home from "./pages/Home"; import New from "./pages/New"; import Diary from "./pages/Diary"; import Notfound from "./pages/Notfound"; import Edit from "./pages/Edit"; const mockData = [ { id: 1, createdDate: new Date("2024-10-01").getTime(), emotionId: 1, content: "1번일기 내용", }, { id: 2, createdDate: new Date("2024-10-10").getTime(), emotionId: 2, content: "2번일기 내용", }, { id: 3, createdDate: new Date("2024-09-09").getTime(), emotionId: 3, content: "3번일기 내용", }, { id: 4, createdDate: new Date("2024-10-04").getTime(), emotionId: 3, content: "3번일기 내용", }, ]; function reducer(state, action) { let nextState; switch (action.type) { case "INIT": { return action.data; } case "CREATE": { nextState = [...state, action.data]; break; } case "UPDATE": { nextState = state.map((item) => item.id === action.data.id ? action.data : item ); break; } case "DELETE": nextState = state.filter((item) => item.id !== action.id); break; default: return state; } localStorage.setItem("diary", JSON.stringify(nextState)); return nextState; } export const DiaryStateContext = createContext(); export const DiaryDispatchContext = createContext(); function App() { const [isLoading, setIsLoading] = useState(true); const [data, dispatch] = useReducer(reducer, []); const idRef = useRef(0); useEffect(() => { const storedData = localStorage.getItem("diary"); if (!storedData) { setIsLoading(false); return; } const persedData = JSON.parse(storedData); if (!Array.isArray(persedData)) { setIsLoading(false); return; } let maxId = 0; persedData.forEach((item) => { if (Number(item.id) > maxId) { maxId = Number(item.id); } }); idRef.current = maxId + 1; dispatch({ type: "INIT", data: persedData, }); setIsLoading(false); }, []); const onCreate = (createdDate, emotionId, content) => { dispatch({ type: "CREATE", data: { id: idRef.current++, createdDate, emotionId, content, }, }); }; if (isLoading) { return <div>데이터 로딩중입니다...</div>; } const onUpdate = (id, createdDate, emotionId, content) => { dispatch({ type: "UPDATE", data: { id, createdDate, emotionId, content, }, }); }; const onDelete = (id) => { dispatch({ type: "DELETE", id, }); }; return ( <> <DiaryStateContext.Provider value={data}> <DiaryDispatchContext.Provider value={{ onCreate, onUpdate, onDelete }}> <Routes> <Route path="/" element={<Home />} /> <Route path="/new" element={<New />} /> <Route path="/diary/:id" element={<Diary />} /> <Route path="/edit/:id" element={<Edit />} /> <Route path="*" element={<Notfound />} /> </Routes> </DiaryDispatchContext.Provider> </DiaryStateContext.Provider> </> ); } export default App; 질문폭탄 죄송합니다ㅠㅠㅠ 왜 저는 새로고침하면 빈배열로 화면에 나타날까요? 로컬스토리지에 저장은 되더라구요그리고 let nextState; 이렇게 저장하면 state값이 바뀔 때 nexState도 초기화 되지 않나요? 초기화 되고 나서 값을 저장한 후 사용해서 상관이 없는건가요?
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
undefined일 경우
const Diary = () => { const params = useParams(); const nav = useNavigate(); const currentDiaryItem = useDiary(params.id); if (!currentDiaryItem) { return <div>데이터로딩중</div>; } const { createdDate, emotionId, content } = currentDiaryItem; const Edit = () => { const nav = useNavigate(); const { onDelete, onUpdate } = useContext(DiaryDispatchContext); const params = useParams(); const currentDiaryItem = useDiary(params.id);Diary컴포넌트와 Edit컴포넌트 둘 다 useDiary로부터 currentDiaryItem을 받아오고 있는데, Diary는 undefined일 때경우를 처리해주고 있는데, Edit컴포넌트는 그렇지 않습니다. useEffect(() => { if (initData) { // undefined일 때 setInput({ ...initData, createdDate: new Date(Number(initData.createdDate)), }); } }, [initData]);위코드는 Editor컴포넌트 안의 코드입니다. 여기서 undefined룰 걸려주기 때문에 Edit컴포넌트에서 처리를 안해도 되는 건가용?
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
Diary.jsx
import { useContext, useState, useEffect } from "react"; import { DiaryStateContext } from "../App"; import { useNavigate } from "react-router-dom"; const useDiary = (id) => { const data = useContext(DiaryStateContext); const [currentDiaryItem, setCurrentDiaryitem] = useState(); const nav = useNavigate(); useEffect(() => { const currentDiaryItem = data.find( (item) => String(item.id) === String(id) ); if (!currentDiaryItem) { window.alert("존재하지 않는 일기입니다."); nav("/", { replace: true }); } setCurrentDiaryitem(currentDiaryItem); }, [id, data]); //data는 왜쓰는지? return currentDiaryItem; }; export default useDiary; 강의 내용코드입니다. 현재의 일기를 가져오는 커스텀훅입니다.여기서 문제는 "존재하지 않는 일기입니다"라는 경고창이 2번뜹니다. http://localhost:5173/diary/1234 처럼 아무숫자나 입력했을 때 그리고 http://localhost:5173/ 으로 이동한 후에 경고창이 한번 더 뜹니다. useEffect가 id가 변함에 따라 계속 실행되어서라는 이유로 알고 있습니다. 그러면 왜 선생님코드에서는 경고창이 2번 뜨지 않았을까용?그리고 의존성 배열에 [id, data] 2가지를 담는 이유가 궁금합니다. 현재 prams.id가 바뀔 때만 작동하게 해도 되지 않을까요? 사용자가 data를 수정하면서 페이지의 파라미터가 바뀌는 상황이 동시에 일어나지 않을 거 같아서요
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
new Date()
const Editor = ({ onSubmit, initData }) => { const nav = useNavigate(); const [input, setInput] = useState({ createdDate: new Date(), // 여기서 그냥 getTime하면 안되나요? emotionId: 8, content: "", }); useEffect(() => { if (initData) { setInput({ ...initData, createdDate: new Date(Number(initData.createdDate)), }); } input의 createdDate와 initData의 createdDate 비교 기준이 new Date()과 new Date().getTime() 로 달라서 useEffect안에서 createdDate: new Date(Number(initData.createdDate)), 이렇게 한다는 건 이해가 갑니다. 다만 처음부터 input의 createdDate를 new Date().getTime()으로 만들면 되지 않을까요?
-
미해결따라하며 배우는 자바스크립트 A-Z
Start 버튼을 연속으로 두 번 누르면 Stop버튼이랑 Reset 버튼이 작동하지 않습니다.
Stop과 Reset이 제대로 작동되도록 해결할 수 있는 방법이 무엇인지 궁금합니다.
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
input의 value속성이 꼭 필요한가요?
<input value={getStringedDate(input.createdDate)} name="createdDate" onChange={onChange} type="date" className="bg-[rgb(236,236,236)] font-xl rounded-md px-[20px] py-[10px]" /> 새로운 일기를 만들때 날짜 input에서 value속성을 'getStringedDate(input.createdDate)'이렇게 설정하고 있는데요 저는 value속성을 넣지 않고도 작동을 합니다. value속성 꼭 적어야 할까요? 단순히 초기값을 설정하기 위함일까요? 아니라면 value속성을 적는 것이 권장되는 이유는 뭘까용?
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
BrowserRouter사용방법
강의 12.3 보다가 의문이 들어서 질문 남깁니다.강의에서 설명하고 사용하셨던 방법과 공식문서에서 BrowserRouter를 사용하는 방법이 달라서 헷갈립니다.두가지 방법이 같은 것인지, 다르다면 어떻게 다른지 알려주세요function App() { return ( <BrowserRouter basename="/app"> <Routes> <Route path="/" /> </Routes> </BrowserRouter> ); }=>공식문서에서는 이렇게 Routes를 BrowserRouter로 감싸서 사용했는데 강의 에서는 그러지 않아서 궁금합니다.!
-
미해결[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
만일 변조된 AccessToken을 요청했을때 사후처리가 궁금합니다.
안녕하세요 강의 너무 잘보고있어요!! 근데 궁금점이 생겼네요강의에서는 AccessToken이 만료되거나 변조되었다면 에러메세지를 전달하고있는데 만약에 변조된 AccessToken을 캐치하고 에러를 프론트로 전달한다면 통상적인 프로세스로는 Refresh토큰을 가지고 Access를 재 발급하지 않나요 ? 그렇다면 만일 공격자가 새로 발급된 AccessToken을 탈취할 수 있는 거 아닌가 라는 생각이 들어서요.. 그렇다면 통상적으로 변조된 AccessToken을 캐치한다면 이를 클라로 에러코드와 같이 전달하고 아예 refresh와 access를 초기화 시키고 재 로그인을 요구하는 것이 옳은 프로세스일지요?
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
Home page에서 getMonthlyData 함수
const getMonthlyData = (pivotDate, data) => { //컴포넌트 밖에서 함수를 만드는 이유? const beginTime = new Date( pivotDate.getFullYear(), pivotDate.getMonth(), 1, 0, 0, 0 ).getTime(); const endTime = new Date( pivotDate.getFullYear(), pivotDate.getMonth() + 1, 0, 0, 0, 0 ).getTime(); return data.filter( (item) => beginTime <= item.createdDate && item.createdDate <= endTime ); };endtime을 0일 23시 59분 59초가 아닌 0일 0시 0분 0초로 설정해도 될까요? 월에서 +1을 했으니 마지막 일도 포함될 거 같아서요!
-
미해결한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
Editor css justify-content 질문
15:04에 .Editor .emotion_section .emotion_list_wrapper에서 justify-content: space-around;해도 아래 사진과 같이 요소를 화면 중심으로 배치할 수 없어서요. 어떻게 해야하는 건지 답변 부탁드립니다.
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
nav('/', { replace: true }); 뒤로가기 방지
import Header from '../components/Header'; import Button from '../components/Button'; import Editor from '../components/Editor'; import { useNavigate } from 'react-router-dom'; import { useContext } from 'react'; import { DiaryDispatchContext } from '../App'; const New = () => { const nav = useNavigate(); const { onCreate } = useContext(DiaryDispatchContext); const onSubmit = (input) => { onCreate(input.createdDate.getTime(), input.emotionId, input.content); nav('/', { replace: true }); }; return ( <div> <Header title={'새 일기 쓰기'} leftChild={ <Button text={'< 뒤로 가기'} onClick={() => { nav(-1); }} /> } /> <Editor onSubmit={onSubmit} /> </div> ); }; export default New; 여기서 nav('/', {replace:true});로 뒤로가기(New 페이지로 가는 것)를 방지했는데,뒤로가기를 한 번 눌렀을 때는 잘 동작하는데두 번 눌렀을 때부터 뒤로 가집니다. 혹시 원래 이런건가요? 아니면 제가 뭔가 잘못한건가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
graphql 에 이렇게 뜨는 버그 어떻게 해결할 수 있나요?
원래는 그렇지 않았는데 전부터 graphql 에서 api 테스트 해보려고 하면 아래에 항상 이런방식으로 글자 나타나고 사라지지 않더라고요.. 맥을 사용하고 있는데 이거 어떤 방식으로 해결할 수 있나요?
-
미해결처음 만난 리액트(React)
코드 오류시 참고하시면 될듯합니다.
영상에 제시한 코드를 사용하면 아래와같은 오류가뜹니다 React 18에서는 ReactDOM.render를 지원하지 않는다고 하네요.. 아래 코드로 수정하니 잘 됩니다 참고 하세요~
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
소괄호 자동 생성
안녕하세요 강사님, 강의 잘 듣고 있어요!!다름이 아니라,강사님 화면에서는 return 뒤에 작성하시고 소괄호가 자동으로 생성되면서 작성한 내용을 감싸주던데, 어떻게 하는건가요?ESLint, Prettier등 설치는 했어요 ㅠ.ㅠ 🚨 아래의 가이드라인을 꼭 읽고 질문을 올려주시기 바랍니다 🚨질문 하시기 전에 꼭 확인해주세요- 질문 전 구글에 먼저 검색해보세요 (답변을 기다리는 시간을 아낄 수 있습니다)- 코드에 오타가 없는지 면밀히 체크해보세요 (Date와 Data를 많이 헷갈리십니다)- 이전에 올린 질문에 달린 답변들에 꼭 반응해주세요 (질문에 대한 답변만 받으시고 쌩 가시면 속상해요 😢)질문 하실때 꼭 확인하세요- 제목만 보고도 무슨 문제가 있는지 대충 알 수 있도록 자세한 제목을 정해주세요 (단순 단어 X)- 질문의 배경정보를 제공해주세요 (이 문제가 언제 어떻게 발생했고 어디까지 시도해보셨는지)- 문제를 재현하도록 코드샌드박스나 깃허브 링크로 전달해주세요 (프로젝트 코드에서 문제가 발생할 경우)- 답변이 달렸다면 꼭 확인하고 반응을 남겨주세요- 강의의 몇 분 몇 초 관련 질문인지 알려주세요!- 서로 예의를 지키며 존중하는 문화를 만들어가요. - 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
-
해결됨[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
cascade 자식이 부모삭제가 맞는건가요??
안녕하세요. 지금 typeORM에서 cascade를 보고있는데fk를 삭제하면 pk가 삭제하는게 일반적인 동작인지가 궁금합니다. User 엔티티에서 onDelete : "cascade"로 설정해두었고삭제는 부모에서 > 자식으로 연결되는 것으로 알고 있습니다. 근데 ProfileModel의 레코드가 삭제되도 Join한 레코드도 삭제되는데자식 > 부모로 삭제가 전파되는게 맞는건지 혼란이옵니다.강의에서도 profile을삭제하니 User레코드가 날아가버리는데 이 현상이 이해 되질않습니다. 부모>자식 cascade를 인한 연쇄 삭제 or update자삭>부모 cascade를 인한 삭제 불가 이게 기존 제 개념인데 제가 잘못알고있던건가 찾아보아도 정보가 좀 엉켜있네요.. typeORM만의 기능인지 SET NULL로 방지해야 하는건지 궁금합니다.
-
해결됨문법 공부 다음엔, 자바스크립트 프로젝트 101
bmi 계산기 질문있습니다.
bmi 계산기 부분에서 display함수 안에 let group; 이렇게 변수 선언만 해주는 이유가 뭔가요? 조금 쉽게 설명부탁드리겠습니다.
-
미해결쌩초보도 4시간 안에 마스터하는 자바스크립트 기초
코드 샌드박스가 업그레이드되서 그런지..
콘솔버튼이 아예 안보이네요..
-
미해결한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
<Editor onCreate={onCreate} />인 이유가 뭘까요
🚨 아래의 가이드라인을 꼭 읽고 질문을 올려주시기 바랍니다 🚨질문 하시기 전에 꼭 확인해주세요- 질문 전 구글에 먼저 검색해보세요 (답변을 기다리는 시간을 아낄 수 있습니다)- 코드에 오타가 없는지 면밀히 체크해보세요 (Date와 Data를 많이 헷갈리십니다)- 이전에 올린 질문에 달린 답변들에 꼭 반응해주세요 (질문에 대한 답변만 받으시고 쌩 가시면 속상해요 😢)질문 하실때 꼭 확인하세요- 제목만 보고도 무슨 문제가 있는지 대충 알 수 있도록 자세한 제목을 정해주세요 (단순 단어 X)- 질문의 배경정보를 제공해주세요 (이 문제가 언제 어떻게 발생했고 어디까지 시도해보셨는지)- 문제를 재현하도록 코드샌드박스나 깃허브 링크로 전달해주세요 (프로젝트 코드에서 문제가 발생할 경우)- 답변이 달렸다면 꼭 확인하고 반응을 남겨주세요- 강의의 몇 분 몇 초 관련 질문인지 알려주세요!- 서로 예의를 지키며 존중하는 문화를 만들어가요. - 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
-
해결됨한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지
섹션8 라이프 사이클 unmount 관련 질문
import { useState } from 'react' import Viewer from './components/Viewer' import Controller from './components/Controller' import { useEffect } from 'react' import { useRef } from 'react' import Even from './components/Even' import './App.css' function App() { const [count, setCount] = useState(0); const [input, setInput] = useState(""); const isMount = useRef(false); //1. 마운트 : 탄생 useEffect(()=>{ console.log("mount") },[]) //2. 업데이터 : 변화, 리렌더링 useEffect(()=>{ if(!isMount.current){ isMount.current = true; return; } console.log("update") }) //3. 언마운트 : 죽음 //useEffect(()=>{console.log(count)},[count, input]) // 의존성 배열, dependency array, deps const onClickButton = (value)=>{ setCount(count + value); } return ( <div className='App'> <h1>Simple Counter</h1> <section> <input value={input} onChange={(e)=>{ setInput(e.target.value) }}/> </section> <section> <Viewer count={count}/> {count % 2 === 0 ? <Even/> : null} </section> <section> <Controller onClickButton = {onClickButton}/> </section> </div> ); } export default App import { useEffect } from "react"; const Even = () => { useEffect(() => { //클린업, 정리함수 return () => { console.log("unmount") }; }, []); return <div>짝수입니다</div>; }; export default Even; 새로고침이나 초기 호출시에도 unmount가 출력되고 홀수로 카운팅이 올라가 컴포넌트가 삭제되는 경우는 update이후 unmount가 정상적으로 출력되는 것을 확인할 수 있는데 짝수로 카운팅이 올라가 컴포넌트가 생성되는 경우는 unmount 이후 update가 됩니다.컴포넌트가 삭제되는 경우에만 unmount가 진행되는 것으로 알고 있는데 혹시 코드에 문제가 있을까 질문드립니다.
-
미해결DOM 인터랙션
이 강좌를 들으면 좋은점이 뭔가요?
안녕하세요.저는 서버개발자로 일을 하고 있지만,영보님 강의를 모두 사서 듣고있는 주니어 개발자입니다.우선 좋은 강좌를 만들어주셔서 너무 감사합니다.앞으로도 좋은 강좌 많이 만들어 주시면 너무나도 감사할것같습니다.현재 돔 인터랙션이라는 강의를 듣고 있고 중반정도 달려왔는데이 강의를 들으면 듣지 않은 사람들에 비해 어떤 경쟁력을갖게 되는지 궁금합니다.영보님께서 강의를 만드신 이유와 의도가 있었을 것 같은데그 부분이 궁금합니다. 그리고 리액트 심화 강의도 혹시 출시 하실 생각이 있으신지궁금합니다.