์ง๊ธ๊น์ง 2๋ฒ์ ํ๋ก์ ํธ์์ ๋ก๊ทธ์ธ/ ํ์๊ฐ์ ํํธ๋ฅผ ๋งก์๋๋ฐ ๊ทธ๋๋ ๋ชจ๋ ๋ก๊ทธ์ธ, ํ์๊ฐ์ ์ ๋ณ๋์ ๊ฒฝ๋ก๋ก ๋ถ๋ฆฌํด์ ๋ง๋ค์๋ค.
๊ทธ๋ฐ๋ฐ ์ด๋ฆฌ์ ๋ฆฌ ๊ตฌ๊ธ๋ง์ ํ๋ค๊ฐ ์์ gif์ฒ๋ผ ํญ ํ์์ผ๋ก ๋ก๊ทธ์ธ๊ณผ ํ์๊ฐ์ ์ ๋ง๋ค์ด๋ณด๊ณ ์ถ์๋ค!
๊ทธ๋์ ๋์ !
์ฌ์ฉํ ๊ธฐ์ ์คํ
React, Typescript, Styled-components
๊ตฌํํ ํ์คํธ
1. ๋ก๊ทธ์ธ/ํ์๊ฐ์ ํญ์ ๋๋ฅด๋ฉด ๋ฒํผ์ด ๊ฐ๊ฐ ๋ก๊ทธ์ธ, ํ์๊ฐ์ ์ผ๋ก ๋ฐ๋๋ค.
2. ํด๋ฆญ๋๋ ๋ก๊ทธ์ธ/ํ์๊ฐ์ ํญ์ css๋ก ํ์ํ๋ค.
3. ์ด๋ฉ์ผ์ @, . ํฌํจ๋๊ณ , ๋น๋ฐ๋ฒํธ๊ฐ 8์๋ฆฌ ์ด์์ผ ๋ ๋ฒํผ์ด ํ์ฑํ๋๋ค.
1. ๋ก๊ทธ์ธ/ํ์๊ฐ์ ํญ์ ๋๋ฅด๋ฉด ๋ฒํผ์ด ๊ฐ๊ฐ ๋ก๊ทธ์ธ, ํ์๊ฐ์ ์ผ๋ก ๋ฐ๋๊ฒ ํ๊ธฐ
ํญ๋ถ๋ถ๊ณผ ํผ๋ถ๋ถ์ ๋๋ ์ ๋ง๋ค์ด์ ๋ถ์ด๋ฉด ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ก๊ทธ์ธ์ด ๋ ์ํ๋ฅผ ์ ์ ์๋ state๋ฅผ ๋ง๋ค์ด์ ๊ด๋ฆฌํ๋ค.
const [isLogin, setIsLogin] = useState(true);
๋ก๊ทธ์ธ ๋ฒํผ์ ๋๋ฅด๋ฉด setIsLogin์ด true๊ฐ ๋๊ณ , ํ์๊ฐ์ ๋ฒํผ์ ๋๋ฅด๋ฉด setIsLogin์ด false๊ฐ ๋๋๋ก ํ๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ ์ํ๋ฅผ ๊ฐ์ง๊ณ ๋ฒํผ์์๋ isLogin์ด true๋ฉด '๋ก๊ทธ์ธ' ๊ธ์๊ฐ, false๋ฉด 'ํ์๊ฐ์ ' ๊ธ์๊ฐ ๋์ค๊ฒ ํ๋ค.
2. ํด๋ฆญ๋๋ ๋ก๊ทธ์ธ/ํ์๊ฐ์ ํญ์ css๋ก ํ์ํ๋ค.
styled-component๋ก ์์ ํ๋ฉด props๊ฐ์ ๋ฐ์์ ์คํ์ผ์ ์ ๋์ ์ผ๋ก ์กฐ์ ํ ์ ์๋ค!
์ฌ๊ธฐ์๋ isLogin ์ํ์ ๋ฐ๋ผ ์์ด ๋ณํ๋ฉด ๋๋๊น isLogin์ props๋ก ๋ฐ์์๋ค.
const AuthTab = styled.div<{ isLogin: boolean }>`
width: 300px;
display: flex;
button {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
/* border-top: 1px solid gray; */
box-shadow: rgba(50, 50, 93, 0.25) 1px 2px 5px -1px,
rgba(0, 0, 0, 0.3) -1px 1px 3px -1px;
border: 0;
border-bottom: 0;
background-color: transparent;
padding: 10px 30px;
flex-basis: 50%;
cursor: pointer;
}
& > button:first-child {
background-color: ${({ isLogin }) => (isLogin ? "#5586eb" : "inherit")};
color: ${({ isLogin }) => (isLogin ? "#ffffff" : "#000000")};
}
& > button:last-child {
background-color: ${({ isLogin }) => (isLogin ? "inherit" : "#5586eb")};
color: ${({ isLogin }) => (isLogin ? "#000000" : "#ffffff")};
}
`;
3. ์ด๋ฉ์ผ์ @, . ํฌํจ๋๊ณ , ๋น๋ฐ๋ฒํธ๊ฐ 8์๋ฆฌ ์ด์์ผ ๋ ๋ฒํผ์ด ํ์ฑํ๋๋ค.
์ด ๋ถ๋ถ์ ํด๊ฒฐํ๊ธฐ ์ํด์๋ input์ onKeyUp ์ด๋ฒคํธ๋ฅผ ํ์ฉํ๋ฉด ๋๋ค.
input์ value ๊ฐ์ ์ ๋ค์ฌ๋ค ๋ณด๊ณ ์๋ค๊ฐ, ์ด๋ฉ์ผ์ @, . ํฌํจ๋๊ณ , ๋น๋ฐ๋ฒํธ๊ฐ 8์๋ฆฌ ์ด์์ผ ๋ ๋ฒํผ์ด ํ์ฑํ๋๋๋ก css ์ฒ๋ฆฌ๋ฅผ ํด์ค๋ค.
์ด๋ฅผ ์ํด์ isActive๋ผ๊ณ ๋จผ์ ์ํ๋ฅผ ์ ์ธํด์ค๋ค.
const [isActive, setIsActive] = useState<boolean>(false);
๊ทธ๋ฆฌ๊ณ input์๋ onKeyUp ์ด๋ฒคํธ๋ฅผ ์ด์ฉํด์ changeButton์ด๋ผ๋ ํจ์๋ฅผ ๋ง๋ค์๋ค.
const changeButton = () => {
email.includes("@") && password.length >= 8
? setIsActive(true)
: setIsActive(false);
};
๊ทธ๋ฆฌ๊ณ ๋ฒํผ์ css ํจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์ํด์ isActive ๊ฐ true์ธ์ง, false์ธ์ง์ ๋ฐ๋ผ css๋ฅผ ๋ฌ๋ฆฌํ๋ค.
<button className={isActive ? "Active" : "Disabled"}>
{isLogin ? "๋ก๊ทธ์ธ" : "ํ์๊ฐ์
"}
</button>
ํด๋ณด๊ณ ์ถ์๋๋ฐ ํด๋ด์ ๊ธฐ์๋ค!!
์ ์ฒด ์ฝ๋
import React, { useState } from "react";
import styled from "styled-components";
const Auth = () => {
const [isLogin, setIsLogin] = useState(true);
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [isActive, setIsActive] = useState<boolean>(false);
const changeButton = () => {
email.includes("@") && password.length >= 8
? setIsActive(true)
: setIsActive(false);
};
return (
<Container>
<AuthTab isLogin={isLogin}>
<button type='button' onClick={() => setIsLogin(true)}>
๋ก๊ทธ์ธ
</button>
<button type='button' onClick={() => setIsLogin(false)}>
ํ์๊ฐ์
</button>
</AuthTab>
<AuthForm>
<InputInfo>
<Input
type='email'
id='id'
placeholder='
EMAIL'
required
value={email}
onKeyUp={changeButton}
onChange={(e) => {
setEmail(e.target.value);
}}
></Input>
<Input
type='password'
id='password'
placeholder='PASSWORD'
required
value={password}
onKeyUp={changeButton}
onChange={(e) => {
setPassword(e.target.value);
}}
></Input>
</InputInfo>
<button className={isActive ? "Active" : "Disabled"}>
{isLogin ? "๋ก๊ทธ์ธ" : "ํ์๊ฐ์
"}
</button>
</AuthForm>
</Container>
);
};
export default Auth;
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
`;
const AuthTab = styled.div<{ isLogin: boolean }>`
width: 300px;
display: flex;
button {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
/* border-top: 1px solid gray; */
box-shadow: rgba(50, 50, 93, 0.25) 1px 2px 5px -1px,
rgba(0, 0, 0, 0.3) -1px 1px 3px -1px;
border: 0;
border-bottom: 0;
background-color: transparent;
padding: 10px 30px;
flex-basis: 50%;
cursor: pointer;
}
& > button:first-child {
background-color: ${({ isLogin }) => (isLogin ? "#5586eb" : "inherit")};
color: ${({ isLogin }) => (isLogin ? "#ffffff" : "#000000")};
}
& > button:last-child {
background-color: ${({ isLogin }) => (isLogin ? "inherit" : "#5586eb")};
color: ${({ isLogin }) => (isLogin ? "#000000" : "#ffffff")};
}
`;
const AuthForm = styled.form`
/* border: 1px solid gray; */
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
width: 300px;
display: flex;
flex-direction: column;
align-items: center;
button {
margin: 10px 0px;
background-color: transparent;
border: 1px solid #81a4ea;
padding: 10px;
width: 88%;
border-radius: 10px;
}
.Disabled {
background-color: inherit;
}
.Active {
background-color: #5586eb;
color: white;
}
`;
const InputInfo = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
`;
const Input = styled.input`
padding: 10px;
margin: 10px 0px;
width: 80%;
border: 1px solid lightblue;
border-radius: 10px;
`;
'๐ฅFrontEnd > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
docusaurus์์ ์ต์ ๋ธ๋ก๊ทธ ๊ธ ๊ฐ์ ธ์ค๊ธฐ (0) | 2023.04.05 |
---|---|
.env ํ๊ฒฝ ๋ณ์ ํ์ผ (0) | 2023.03.10 |
Next.js๋ ๋ฌด์์ธ๊ฐ? ๋ด๊ฐ ์ฌ์ฉํ๋ฉด์ ๋๋ Next.js์ ์ฅ์ ์? (0) | 2022.11.08 |
axios.get์ fetch ์ฐจ์ด (0) | 2022.09.05 |
TIL) ๋ฆฌ์กํธ์์ <a> ํ๊ทธ? Link ์ปดํฌ๋ํธ? (0) | 2022.09.02 |