🔎 props
- 여러 개의 변수를 하나의 객체로 묶어서 자식 컴포넌트에 전달하는 방식으로 여러데이터를 하나의 객체로 전달
- 부모 컴포넌트에서 자식 컴포넌트로 값을 전달할 때 {}를 사용하여 JavaScript 표현식을 전달
- 구조 분해 할당(destructuring)을 통해 props 객체에서 필요한 값만 꺼내서 사용이 가능하다
ex)
const ParentComponent = () => {
const name = "John";
const age = 30;
const job = "Developer";
// 여러 개의 변수를 하나의 객체로 묶어서 전달
return <ChildComponent name={name} age={age} job={job} />;
};
const ChildComponent = ({ name, age, job }) => {
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
<p>Job: {job}</p>
</div>
);
};
- 부모 컴포넌트에서 name, age, job 값을 각각 props로 자식 컴포넌트에 전달
- 자식 컴포넌트에서는 구조 분해 할당을 사용하여 name, age, job을 사용
🔎 children
ex)
function Wrapper({ children }) {
return <div className="wrapper">{children}</div>;
}
<Wrapper>
<p>이 내용은 children으로 전달됩니다.</p>
</Wrapper>
🔎 기본 HTML 속성 (리액트에서 사용 가능)
- 리액트는 JSX를 사용하기 때문에 일반 HTML 속성을 사용할 수 있지만, 일부 속성은 JavaScript 표기법에 맞춰 변경되었기때문에 숙지하는게 좋다
| HTML 속성 | 리액트 속성 (JSX) |
|---|
| class | className |
| for | htmlFor |
| tabindex | tabIndex |
- a 태그를 사용하지 못하기 때문에 대신 Link 사용
- for 는 자바스크립트 예약어이기 때문에 htmlFor 사용
- htmlFor는 태그와 입력 필드(input)를 연결할 때 사용
function InputExample() {
return (
<div>
<label htmlFor="username">Username:</label> {/* htmlFor 사용 */}
<input id="username" type="text" />
</div>
);
}
export default InputExample;
🔎 리액트 이벤트 핸들링 속성
- 리액트 이벤트는 CamelCase를 사용하며, 함수 참조를 전달
| HTML 이벤트 | 리액트 이벤트 |
|---|
| onclick | onClick |
| onchange | onChange |
| oninput | onInput |
ex)
function App() {
const handleClick = () => {
alert("버튼 클릭!");
};
return <button onClick={handleClick}>Click Me</button>;
}
🔎 state
- 리액트의 state는 화면에 출력하거나 동적으로 변화를 관리하는 변수 역할을 한다
- 직접 값을 변경하지 않고, 반드시 setState 함수를 통해 업데이트해야 한다
EX)
import React, { memo, useState } from "react";
import styled from "styled-components";
const MyStateContainer = styled.div``;
const MyState = memo(() => {
/**
* state(상태)값 정의
* - 이 페이지 안에서 유효한 전역변수 같은 개념
* - 화면에 출력할 용도의 변수라고 이해하면 된다
* - const [변수이름, 변수에대한 setter함수] = React.useState(변수의 기본값);
* - state값은 대입연산자를 사용하여 직접 변경할 수 없고 반드시 setter 를 통해서만 변경 가능하다
*/
const [myName, setMyName] = useState("");
const [myPoint, setMyPoint] = useState(50);
// 이벤트 핸들러로 사용될 함수는 컴포넌트 함수 안에서 정의된다
const onMyNameChange = (e) => {
// 바닐라 js 방식의 입력값 출력
// ---> 출력할 대상을 의미하는 객체를 직접 제어해야한다
// document.querySelector("#output").inner = e.currentTarget.value;
// 리액트는 상태변수의 값을 변경하기 위해 setter함수를 사용해야 한다
// --> 상태변수에 대한 직접 대입은 에러이다 ex) myName = e.currentTarget.value;
// setter 함수를 통해 변경된 상태 변수는 모든 출력 위치에 자동 반영된다
setMyName(e.currentTarget.value);
};
return (
<MyStateContainer>
<h2>MyState</h2>
<div>
<label htmlFor="myNameInput">이름: </label>
{/* 1) 상태변수 myName 이 value 속성에 연결된 입력요소 */}
{/* 2) 이벤트 연결은 `on + 이벤트이름` (대소문자 주의), 반드시 함수와 연결해야한다 onChange */}
{/* 3) value 속성은 반드시 상태변수만 연결가능하고, value속성을 사용할경우 onChange 이벤트를 통해 상태변수에 입력값을 갱신해 줘야 한다 */}
{/* 4) 기존 HTML에서의 value 속서아은 defaultValue 속성을 사용한다 (기본값 설정) */}
<input
type="text"
id="myNameInput"
value={myName}
onChange={onMyNameChange}
></input>
</div>
<div>
<label htmlFor="myPointInput">점수: </label>
<input
id="myPointInput"
type="range" // 막대기로 움직일수있게하는,,???
min="0"
max="100"
value={myPoint}
step="1"
// 이벤트 핸들러를 익명 화살표 함수 형식으로 정의한 경우
onChange={(e) => setMyPoint(e.currentTarget.value)}
></input>
</div>
<h2>{myName}님의 점수는 {myPoint}점 입니다</h2>
</MyStateContainer>
);
});
export default MyState;
🔎 날짜처리(Day.js 사용)
- 리액트에서 날짜 처리는 일반적으로 Day.js와 같은 라이브러리를 사용하여 간단히 처리할 수 있다
- for 날짜 처리 패키지로 (yarn add dayjs) 설치해줘야함
- setter 함수를 통해 json 형태의 상태값을 갱신할때는 반드시 원본 객체를 직접 변경하지 않고, 새로운 객체를 만들어서 업데이트한다
=> 이유는??? 상태를 직접 변경하면 리액트가 상태 변화를 추적하지 못해서 화면이 자동으로 업데이트되지 않음!!!
EX-1)
const newDate = {...myDate}; // 기존 객체의 복사본을 만들고, 그 위에 수정
newDate.year = 2024; // 새로운 객체에서 수정
setMyDate(newDate); // 새로운 객체를 상태로 설정
EX-2)
/**
* useState 를 사용하여 날짜 범위 선택 기능 구현
*/
import React, { memo, useState } from "react";
import styled from "styled-components";
// for 날짜 처리 패키지로 (yarn add dayjs) 설치해줘야함
import dayjs from 'dayjs';
const DateRange1Container = styled.div``;
const DateRange1 = memo(() => {
// dayjs 객체 리턴 받는다
const day = dayjs();
/**
* 화면에 출력할 상태값을 JSON 객체 myDate로 정의하고
* 이 객체의 값을 갱신할 수 있는 함수를 setMyDate 로 선언
*/
const[myDate, setMyDate] = useState({
startDate: day.format("YYYY-MM-DD"),
endtDate: day.format("YYYY-MM-DD")
});
return (
<DateRange1Container>
<h2>DateRange1</h2>
<h3>{myDate.startDate} ~ {myDate.endtDate}</h3>
<div>
<button type="button" onClick={e => {
// setter 함수를 통해 json 형태의 상태값을 갱신할때는 반드시 원본 객체를 직접 변경하지 않고, 새로운 객체를 만들어서 업데이트해야 한다
const newDate = {...myDate};
// dayjs 객체를 사용ㅎ여 15일전을 계산하여 설정함
newDate.startDate = day.add(-15, 'd').format("YYYY-MM-DD");
setMyDate(newDate);
}}>15일</button>
{/* 1개월, 3개월, 6개월, 1년전을 계산하여 설정함 */}
{/* 월(M)만 분단위(mm)와 구별하기 위해 대문자로 사용한다 */}
{/* 기본설정이 startDate: day.format("YYYY-MM-DD"), endtDate: day.format("YYYY-MM-DD") 이기때문에
setMyDate({...myDate, startDate: day.add(-1, 'M').format("YYYY-MM-DD")}) 를 따로 설정해주면 맞춰서 설정가능 */}
<button type="button" onClick={ e => setMyDate({...myDate, startDate: day.add(-1, 'M').format("YYYY-MM-DD")})}>1개월</button>
<button type="button" onClick={ e => setMyDate({...myDate, startDate: day.add(-3, 'M').format("YYYY-MM-DD")})}>3개월</button>
<button type="button" onClick={ e => setMyDate({...myDate, startDate: day.add(-6, 'M').format("YYYY-MM-DD")})}>6개월</button>
<button type="button" onClick={ e => setMyDate({...myDate, startDate: day.add(-1, 'y').format("YYYY-MM-DD")})}>1년</button>
</div>
</DateRange1Container>
);
});
export default DateRange1;