์ด๋ฒ์๋ ์ ์์ฐพ์์ค๋ ์ถ์๋ ์ํ๊ด๋ฆฌ์ ํผ๋์ด ๋ค์๊ธ ์ฐพ์์๋ค.๐ต
๐ ๋ ์ง data state๋ฅผ ์ด์ฉํ CSS ๋ณํ
โ ์ํฉ
์ฒดํฌ์ธ๊ณผ ์ฒดํฌ์์ ๋๋ ์ง์ ๊ทธ ์ฌ์ด๋ฅผ CSS ๋ก ํ์ํ๊ธฐ
์บ๋ฆฐ๋๋ฅผ ๋ง๋ค๊ณ ํด๋ฆญ์ ๋๋ฅด๋ฉด ํด๋น dataset์ ๋ฐ์ ContextAPI๋ก ๊ด๋ฆฌํ๋ CheckIn, CheckOut ์ ๋ฐ์์์ผฐ๋ค.
click ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ๊ทธ ๊ฐ๋ฅ์ฑ์ ์กฐ๊ฑด๋ฌธ์ผ๋ก ๋น๊ตํ์ฌ CheckIn, CheckOut ์ ๋ฐ์ํ๋ ๋ฐฉ์์ผ๋ก dataํ๋ฆ์ ์งฐ๋๋ฐ
์ฌ๊ธฐ์ ๋ฌธ์ ๋ ํด๋ฆญ๋ ๋ ์ง์ ์ํ๊ด๋ฆฌ๋ค.
CheckIn, CheckOut data๋ ์ ์ญ๊ด๋ฆฌ๊ฐ ๋๊ณ ์๋๋ฐ
clickedData๋ click์ด๋ฒคํธ (handleTdBtnClick )์์์๋ง ๊ด๋ฆฌ๋๊ณ ์๊ธฐ ๋๋ฌธ์
rendering์์ ํด๋น ๊ฐ์ ๊ฐ์ ธ์ฌ ์ ์๋ ๋ฌธ์ ๊ฐ ์๊ธด๊ฒ์ด๋ค.
์ฌ๊ธฐ์ ๋ด๊ฐ ๋ด๋ฆฐ ํด๊ฒฐ๋ฐฉ๋ฒ์ ํฌ๊ฒ ๋๊ฐ์ง
1) clickedData๋ฅผ useState๋ก ๊ด๋ฆฌํ์
์ฅ์ : ์ ์ญ์ํ์ ์ต์ํ
2) clikedData๋ฅผ ์ ์ญ์ํ์ ์ถ๊ฐํ์
์ฅ์ : ์ผ๊ด๋ ๋ ์ง data๊ด๋ฆฌ
---> ๋ค ์๋์๋ค. ์ ๋ต์ ์๋ก์ด ์์ฑ์ ๋ถ์ฌํ์ฌ ์กฐ๊ฑด์ผ๋ก ๋น๊ตํ๋ฉฐ ๋ ๋๋ง!
1) useState ์๋
1)๋ฒ ๋ฐฉ๋ฒ์ด ์ ์ญ์ํ๋ฅผ ์ต์ํ ํ๋ ๋ฐฉํฅ ๊ฐ์ ์งํํ์ง๋ง
baseball๊ณผ ๋น์ทํ ๋ฌธ์ ๋ก ์คํจํ๋ค.
clicke ์ด๋ฒคํธ
const handleTdBtnClick = (e) => {
const [clickedYear, clickedMonth, clickedDay] = e.target.dataset.day
.split('-')
.map(Number);
setSelectedDay(new Date(clickedYear, clickedMonth, clickedDay));
//...์ค๋ต
Component ๋ ๋๋ง ๋ถ๋ถ
return (
<DayTd key={idx}>
<DayTdButton
data-day={`${year}-${month}-${day}`}
onClick={(e) => handleTdBtnClick(e)}
dayCliked={selectCheckInDay === selectedDay}
>
ํด๋ฆญ์ -> clickedData ๊ฐฑ์ -> checkInData ๊ฐฑ์
์ด ์์ผ๋ก ๋ก์ง์ ์ง๋ฉด ๋ ๋๋ง ์ ์ ์ฉ๋ ๊ฒ์ด๋ผ ์๊ฐํ๋๋ฐ,
ํด๋ฆญ๋๋ ์๊ฐ ๋ ๋๋ง์ ์งํ๋๊ณ -> useState์ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์๋๊ธฐ ์ ์ ๋ ๋๋ง์ด ํ์ฐจ๋ก ์๋ฃ๋์๊ธฐ ๋๋ฌธ์ -> ํ๋ฉด์ ํํํ CSS๋ ๋ํ๋์ง ์๋๋ค.
2) selectorContext ์ clickeddata ์ถ๊ฐ
const [calendarData, calDispatch] = useReducer(calendarReducer, {
checkIn: { year: 0, month: 0, day: 0 },
checkOut: { year: 0, month: 0, day: 0 },
});
const [calendarData, calDispatch] = useReducer(calendarReducer, {
checkIn: { year: 0, month: 0, day: 0 },
checkOut: { year: 0, month: 0, day: 0 },
clicked: { year: 0, month: 0, day: 0 },
});
์ด๋ ๊ฒ ์ํ data๋ฅผ ์ถ๊ฐํ๋ค .
ํ์ง๋ง ์ฌ์ค ์ด ๋ฐฉ๋ฒ๋ useState์ ๊ฐ์ ์๋ฏธ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ ํ์์ผ๋ก ๋ํ๋์ง ์์๋ค.
3) ๋ ๋๋ง ๋น์์ dataset๊ณผ ๋น๊ต
Component ๋ ๋๋ง ๋ถ๋ถ (์ )
return (
<SingleCalDiv>
<tbody>
{monthArr?.map((week, idx) => (
<DayTr key={idx}>
{week?.map((day, idx) => (
<DayTd key={idx}>{day}</DayTd>
))}
</DayTr>
))}
</tbody>
</SingleCalDiv>
);
};
Component ๋ ๋๋ง ๋ถ๋ถ (ํ)
return (
<SingleCalDiv>
<tbody>
{monthArr?.map((week, idx) => (
<DayTr key={idx}>
{week?.map((day, idx) => {
const checkInTime = checkInDate.getTime();
const checkOutTime = checkOutDate.getTime();
const clickedTime = new Date(year, month, day).getTime();
return (
<DayTd
key={idx}
day={day}
dayInterval={
checkInTime <= clickedTime && clickedTime <= checkOutTime
}
>
<DayTdButton
disabled={handleDisabled(day)}
day={day}
data-day={`${year}-${month}-${day}`}
onClick={(e) => handleTdBtnClick(e)}
dayClicked={
checkInTime === clickedTime ||
checkOutTime === clickedTime
}
>
{day}
</DayTdButton>
</DayTd>
);
})}
</DayTr>
))}
</tbody>
</SingleCalDiv>
);
};
styled-components
const DayTd = styled.td`
background: ${({ day, dayInterval }) =>
dayInterval && day !== ' ' ? '#f2f2f2' : 'none'};
box-shadow: ${({ day, dayInterval }) =>
dayInterval && day !== ' '
? '0 0 4px 0 #F2F2F2, 4px 0 4px 0 #F2F2F2'
: 'none'};
`;
const DayTdButton = styled.button`
background-color: ${({ dayClicked }) => (dayClicked ? '#333' : 'none')};
color: ${({ dayClicked }) => (dayClicked ? '#fff' : 'none')};
:hover {
box-shadow: ${({ day }) => (day !== ' ' ? '0 0 0 1px #333 inset' : 'none')};
cursor: ${({ day, disabled }) =>
day === ' ' || disabled ? 'default' : 'pointer'};
}
`;
์ฒดํฌ์ธ, ์ฒดํฌ์์๊ณผ ๋ ๋๋ง ๋๋ DayTdButton์ dayClicked ์์ฑ์ ์ฃผ๊ณ
ํด๋น ์์ฑ์ด true์ด๋ฉด ๊ฒ์ ์์์ด ๋ค์ด๊ฐ ์ ์๊ฒ styledComponents์์ ์กฐ์ ํ๋ค.
๐ table์ border ์์ฑ
hover ์ border๋ฅผ ์ฃผ๋ ๊ณผ์ ์์ ์ฌ์ํ ํคํ๋์ด ์์ด๋๋ฐ
๋ถ๋ช box-sizing: border-box๋ฅผ ์ฃผ๋๋ฐ๋ ๋ถ๊ตฌํ๊ณ ์ฐ๊ธ๊ฑฐ๋ฆฌ๋ ๊ฒ์ด์๋ค.
padding์ ์ค์ ํ์ธํด๋ณด๋ box-sizing์ด ์๋จน๋ ๊ฒ์ ํ์ธํ๋ค.
table์ td์๋ box-sizing์ด ์๋จน์๋ค ...... (์์ฒญ๋๊ฒ๊ณ ์ํจ
<- ๋ด์ฉ์ด ๋ค ์ฑ์์์ ๋ ๋ฌธ์ ์๋ ๋ชจ์ต
const DayTdButton = styled.button`
background-color: ${({ dayClicked }) => (dayClicked ? '#333' : 'none')};
color: ${({ dayClicked }) => (dayClicked ? '#fff' : 'none')};
:hover {
box-shadow: ${({ day }) => (day !== ' ' ? '0 0 0 1px #333 inset' : 'none')};
cursor: ${({ day, disabled }) =>
day === ' ' || disabled ? 'default' : 'pointer'};
}
`;
๋ฌ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค ๋ ๊ณต๊ฐ์ ์ฐจ์งํด์ผ ํด์ " " ๊ณต๋ฐฑ์ผ๋ก ๋ฃ์ด์คฌ๋ ๋ถ๋ถ์ด
<td> ๋ด์ฉ์ด ์์ด ์ด๊ธ๋ ๊ฒ์ด์๋ค .
hover ์ border ๊ฐ ์๋ box-shadow๋ฅผ ๋ฃ์์ผ๋ก์จ ํด๊ฒฐํ๋ค.
๐ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋๋ฐ ๋์์ ์ค Raccon๊ณผ DD์๊ฒ ๊ฐ์ฌ์ ๋ง์์ ..
๐ Canves๋ฅผ ์ด์ฉํ ์๊ธ Slider
์๊ธ ์ฌ๋ผ์ด๋๋ฅผ ๊ตฌํํ๋๋ฐ๋ Jenny๊ฐ ๋ง์ ๊ณต์ ์ธ์ ๋ค.โฝ๏ธ๐..
ํด๋น ๋ถ๋ถ์ ๊ธธ์ด ๊ธ์ด์ง ๊ฒ๊ฐ์ ๋ค๋ฅธ ๊ฒ์๊ธ๋ก ์ ๋ฆฌํ๋ค.
https://rrecoder.tistory.com/145
'๐ฟ Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SidePJ] ๊นํ๋ธ Issue Cracker 1๋ถ - ํ๋ก์ ํธ ์์ (0) | 2021.06.29 |
---|---|
[SidePJ] airdnd 3๋ถ - ํ๊ณ ์ ๋ง๋ฌด๋ฆฌ (2) | 2021.06.06 |
[SidePJ] React ๋ชจ๋ฌ ์์ญ ๋ฐ ํด๋ฆญ์ ๋ซ๊ธฐ (0) | 2021.06.03 |
React๋ก Slider ๊ตฌํ & React์์ Canvas๋ก ๊ณก์ ๊ทธ๋ํ ๊ทธ๋ฆฌ๊ธฐ (+globalCompositeOperation ) (0) | 2021.06.02 |
[SidePJ] airdnd 1๋ถ - ํ๋ก์ ํธ ์์ ! (0) | 2021.05.28 |
๋๊ธ