71일차 - react tutorial 3탄

·2024년 3월 25일

react

리액트를 배우면서 생긴 궁금증

  • NumberRecorderForm 과NumberRecorderListItem을 아래에 선언해도 App이 인식을 할까?

내 생각의 흐름

  • 그냥 순전히 궁금해서 순서를 바꿔봤는데 인식을 했다. 내가 알기로는 컴퓨터가 코드를 읽을때는 위에서 아래로 읽는데 아직 선언되지도 않은 저 둘을 인식한게 신기했다.
  • 그래서 gpt한테 물어봤는데 리액트는 컴포넌트 트리라는 구조가 있어서 react의 가상 DOM 및 렌더링 메커니즘에 의한 것이다!

react map이용한 값 수정

const NumberRecorderForm = ({ num, setNum, saveNumber, clearNumbers }) => {
	return (
		<>
			<div>
				<span>숫자 : {num}</span>
				&nbsp;
				<button onClick={() => setNum(0)}>취소</button>
			</div>
			<div>
				<button onClick={() => setNum(num + 1)}>증가</button>
				&nbsp;
				<button
					onClick={() => {
						num == 0 ? setNum(0) : setNum(num - 1);
					}}
				>
					감소
				</button>
				&nbsp;
				<button onClick={saveNumber}>기록</button>
				&nbsp;
				<button onClick={clearNumbers}>전체기록삭제</button>
			</div>
		</>
	);
};
const NumberRecorderList = ({ recordNums, setRecordNums, removeNumber }) => {
	return (
		<>
			<div>
				{recordNums.length == 0 ? (
					<span>기록 없음</span>
				) : (
					<>
						<h5>기록</h5>
						<ul>
							{recordNums.map((number, index) => (
								<NumberRecorderListItem
									key={index}
									number={number}
									recordNums={recordNums}
									setRecordNums={setRecordNums}
									index={index}
									removeNumber={removeNumber}
								/>
							))}
						</ul>
					</>
				)}
			</div>
		</>
	);
};

const NumberRecorderListItem = ({
	index,
	number,
	recordNums,
	setRecordNums,
	removeNumber
}) => {
	const [inputNumberValue, setInputNumberValue] = useState(number);
	const [editModeStatus, setEditModeStatus] = useState(false);

	const modifyNumber = () => {
		if (number == inputNumberValue) return;
		
		if (inputNumberValue == ''){
			setInputNumberValue(number);
		}
		
		setRecordNums(recordNums.map((_number,_index) => _index == index ? inputNumberValue : _number));
		setEditModeStatus(false);
	};

	const readView = (
		<>
			<button onClick={() => setEditModeStatus(true)}>수정</button>
		</>
	);

	const editView = (
		<>
			<input
				type="number"
				placeholder="숫자 써"
				min="0"
				value={inputNumberValue}
				onChange={(e) => setInputNumberValue(e.target.value)}
			/>
			&nbsp;
			<button onClick={modifyNumber}>수정 완료</button>
			&nbsp;
			<button onClick={() => setEditModeStatus(false)}>수정 취소</button>
		</>
	);

	return (
		<>
			<li>
				<span>
					{index + 1}: {number}
				</span>
				&nbsp;
				<button onClick={() => removeNumber(index)}>삭제</button>
				&nbsp;
				{editModeStatus ? editView : readView}
			</li>
		</>
	);
};

const App = () => {
	const [num, setNum] = useState(0);
	const [recordNums, setRecordNums] = useState([10, 20, 30]);

	const saveNumber = () => {
		setNum(0);
		setRecordNums([...recordNums, num]);
	};

	const removeNumber = (index) => {
		setRecordNums(recordNums.filter((_, _index) => _index != index));
	};

	const clearNumbers = () => {
		setRecordNums([]);
	};

	return (
		<>
			<NumberRecorderForm
				num={num}
				setNum={setNum}
				saveNumber={saveNumber}
				clearNumbers={clearNumbers}
			/>
			<NumberRecorderList
				recordNums={recordNums}
				setRecordNums={setRecordNums}
				removeNumber={removeNumber}
			/>
		</>
	);
};

tailwind, daisyUI로 jsx 가져오기!

리액트(React), tailwind, daisyUI 문제 풀기

문제 직면

  • 처음에 증가버튼으로 잘 증가하다가 안쪽화살표버튼 누르고 다시 증가버튼누르니까 1만 추가됨..1이 올라가는게 아니라 문자열 1이 추가되는데 뭐가 문제일까?
  • gpt한테 물어보니까 onChange함수는 항상 문자열(string)을 반환한다..라는데 진짜? 그래서 parseInt해주니까 바로 문제해결.. 럴수 럴수..
const App = () => {

	const [inputValue, setInputValue] = useState(0);

	const handleInputChange = (e) => {
		setInputValue(parseInt(e.target.value));
	};

	return (
		<>
			<form  className="h-full flex items-center justify-center gap-x-[10px]" onSubmit={(e) => e.preventDefault()}>
					<input
						type="number"
						min="1"
						onChange={handleInputChange}
						value={inputValue}
						placeholder="Type here"
						className="input input-bordered w-full max-w-xs"
					/>
					<button
						type="submit"
						onClick={() => setInputValue(inputValue + 1)}
						className="btn btn-outline btn-primary"
					>
						증가
					</button>
			</form>
		</>
	);
};

react로 Todo 만들어보기!

const TodoWriteForm = ({ setNewTodoTitle, newTodoTitle, addTodo }) => {
	return (
		<div className="flex gap-x-3">
			<input
				className="input input-bordered"
				type="text"
				placeholder="할 일 적어"
				value={newTodoTitle}
				onChange={(e) => setNewTodoTitle(e.target.value)}
			/>
			<button className="btn btn-primary" onClick={addTodo}>
				할 일 추가
			</button>
		</div>
	);
};

const App = () => {
	const [todos, setTodos] = useState([]);
	const [newTodoTitle, setNewTodoTitle] = useState("");

	const addTodo = () => {
		if(newTodoTitle.trim().length == 0) return;
		
		setTodos([...todos, newTodoTitle]);
		setNewTodoTitle("");
	};

	return (
		<>
			<TodoWriteForm
				newTodoTitle={newTodoTitle}
				setNewTodoTitle={setNewTodoTitle}
				addTodo={addTodo}
			/>
			<hr />
			<div>{JSON.stringify(todos)}</div>
		</>
	);
};

TODO

리액트(React), 레코드 폼과 레코드 리스트로 컴포넌트 분리
를 fork 해서

  • NumberRecordListItem 분리 [o ]
  • 수정 버튼 넣기 [ o]
  • 수정 버튼 누르면 다시 일반모드로 변경 [ o]
  • 수정모드에서 input 만들기 [o ]
  • 수정모드에서 input 값 변경 가능하도록 [o ]
  • 수정 완료 누르면 원래 보이던 값이 변경되도록 [ o]
  • 수정시 음수 금지 [ ]
  • 수정 취소시 input 값을 초기화 [ ]
  • setTimeOut, setInterval
  • 과정다 끝나고 해볼만한것.
    • 데이터 공부 (kmong 분석 및 시각화)

느낀점(현재 내 상태 체크)

  • 선생님이 내준 과제(?)인 '리액트(React), 레코드 폼과 레코드 리스트로 컴포넌트 분리'를 fork해서 수정 취소시 input 값을 초기화 까지 문제를 푸는 걸 해봤는데.. 생각보다 react를 제대로 복습을 안했는지 선생님이 이때 어떤식으로 변화를 줬고 어떤식으로 리팩토링 했는지 잘 기억이 안났었다. 온전히 내것으로 만들기 위해서는 좀 더 많이 사용해봐야할 것 같다. 아직 구조가 익숙하지 않아서인가?
profile
우당탕탕 연이의 개발일기

1개의 댓글

comment-user-thumbnail
2024년 3월 26일

gpt를 맛본 당신.
이젠 gpt없이 살아갈 수 없다.

답글 달기