리액트 실습 - 컴포넌트 이해하기

박관형·2024년 5월 31일

로그인 창을 만들며 리액트를 이해해보자!

먼저 main component생성 -> src파일 안에 sign-in-form.jsx & sign-up-form.jsx 파일 생성

 const SignInForm = () =>{
     return <div/>
 } 
 export default SignInForm

기본 컴포넌트의 시작의 위와 같은 형태로 시작한다고 인지하면 도움이된다.
함수이며 html을 반환하는 함수/ export로 반환하여 다른 컴포넌트와 함께 활용할수있다.

SignUpForm도 같은 형태로 컴포넌트를 생성해주자.

렌더링될 Main 컴포넌트도 동일한 형태로 시작하며 Wrapper태그 안에 SignInForm , SignUpForm 태그를 넣어주자

 const Main = () => { 
return <Wrapper>
              <SignInForm/>
              <SignUpForm/>
          </Wrapper>
}

우리는 js파일에 css문법 작성이 가능한 style-components를 활용해볼것이다

React는 JSX를 사용해서 이미
JavaScript가 HTML을 포함하고 있는 형태를 취하고 있는데, 여기에 CSS-in-JS 라이브러리만 사용하면 CSS도 손쉽게 JavaScript에 삽입할 수 있습니다.

  • Styled Components는 styled-components라는 NPM 패키지명을 가지고 있는데
    React 프로젝트에 npm 커맨드로 설치할 수 있다.

$ npm i styled-components
// 설치 명령어

설치 후에 package.json에 styled-components가 추가된 것을 확인할 수 있습니다.

"dependencies": {
      "styled-components": "^6.1.11",
}

그후 위에서 설치한 styled 함수를 임포트하여 사용할수있다.

import styled from 'styled-components'

Wrapper태그에 다음과 같은 형태로 css를 적용시킨 후

const Wrapper = styled.div height: calc(100vh - 140px); display: flex; flex-direction: column; justify-content: center; align-items: center;

npm -start를하게되면 메인 컴포넌트 안에 내용들과 작성된 css까지 잘 입힌 모습을 확인할 수 있다.
그런데
스타일 컴포넌트(Wrapper)와 일반 컴포넌트(SignInForm)를 육안으로 분리하기 힘들다.
스타일 컴포넌트를 분리하여 객체로 만들어 사용해보자!

팁 하나!

const S = {
  Wrapper : Wrapper
  }
 // 위와 같이 키와 value(값)이 같으면
 ---
    const S = {
  Wrapper 
  }
//이렇게 축약해 사용할수있다.

위와 같은 형태로 객체로 분리하여 만들어준후 분간하기 어려웠던
스타일 컴포넌트(Wrapper) 앞에 .접근법을 활용하여 (S.Wrapper) 로 분간해주자

이제 밑과 같은 형태로 스타일 이들어가있는 Wrapper안에 Header와 Container도 만들어줄것이다.

    <Wrapper>
        <Container>
                </Header>
                </SignInForm>
                </SignUpForm>
        <Container/>
     <Wrapper/>

작성 후 컨테이너와 나머지 컴포넌트에도 모두 스타일을 적용시켜주자
Wrapper와 같이 Container,Header,SignIn,Signup 모두 스타일을 적용시켜주었다.

const Main = () => {
return <S.Wrapper>
        <S.Container>
            <S.Header>
                <S.Tab>Sign-In</S.Tab>
                <S.Tab>Sign-Up</S.Tab>
            </S.Header>
        <SignInForm/>
        <SignUpForm/>
        </S.Container>
       </S.Wrapper>

}

- 스타일을 모두 담은 메인 컴포넌트 완성

그렇게 되면 Sign in form 과 up form이 두개 다 보이며 마우스가 hover 되어있을때에만 색이 바뀐는 것을 볼수있다

  &:hover{
        background-color: #0fe9e5;
    }
  Tab 스타일 컴포넌트 에 hover하면 색이 바뀌도록 설정해주었다.

내가 해야할일은 Sign in 을 클릭했을때 색이 들어오며 Sign in form 만 보이는것을 원하기 떄문에 그에 맞춰서 다시 코드를 짜보자

먼저 sign in form과 up form을 나누어주기위해 변수를 설정해주자
Main 컴포넌트 안에 let formState = "SIGN-IN"을 작성한다
(만약 변수 안에 불리언 값이 들어간다면 is를 붙여주는것이 좋다 ex let isFormSignIn = true)

  • 들어가기전 내가 변수를 왜 선언했는지 어떻게 사용할것인지 다시 한번 생각해보자

      {
       formState === 'SIGN-IN' ? <SignInForm/> :  <SignUpForm/>
       }

    삼항 연산자를 활용해 fromState가 'SIGN-IN'이 맞다면(true) SignInForm을 보여주고 아니라면 SignUpForm 을 보여줘라!
    (formState가 자바스크립트 변수이기 때문에 중괄호{}를 꼭 써줘야한다)

    • <S.Tab>Sign-In</S.Tab>
    • <S.Tab>Sign-Up</S.Tab>
      에 속성(props)를 전달하여 스타일이 작성된 Tab에서 사용할것이다.
       <S.Tab isSelected={formState === 'SIGN-IN'}>Sign-In</S.Tab>
       
       <S.Tab isSelected={formState === 'SIGN-UP'}>Sign-Up</S.Tab>

첫번째 탭 Sign-In 이 선택되는 기준은 방금 위에서 작성한 코드 "formState === 'SIGN-IN'"
( formState의 값이 'SIGN-IN'이 맞냐!이다)

위 처럼 작성해줌으로써 props의 값이 Tab에 전달된것이다.
값을 사용하기 위해서 스타일을 작성한 Tab에
콜백함수${() => {}}를 작성하여 전달한 값을 가져온다

    ${(props) => props.isSelected && 'backgroundColor: #e0e0e0'}
    const Tab = styled.div`
        width: 50%;
        cursor: pointer;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 28px;
        padding: 16px;
        font-weight: 600;
        ${(props) => props.isSelected && 'backgroundColor: #e0e0e0'}
        &:hover{
            background-color: #e0e0e0;
        }
    `

전달이 완료되었다면 클릭 이벤트를 부여해보자
각각 SIGN IN 과 SIGN UP을 클릭하게되면 어떻게 실행될지 예상해보자.
클릭하는 버튼에 따라 formstate 값이 바뀌게 될것이다.
(그렇다면 변수에 "SIGN-IN"이 아니라 숫자 0이나 아무런 값을 넣어도 상관이 없는걸까?)

이벤트 함수 정의하기 (이벤트를 정의할때 hadle,On 자주씀)

 const handlePressSignTab = () = {}
  • 이 이벤트 함수는 매개변수로 tabName을 받을것이고 내가 정의했던 변수 formState를 tabName으로 바꿔주는 기능을 넣을것이다.
>    const handlePressSignTab = (tabName) => {
            formState = tabName
        }
        
         // 왜"SIGN-IN"을 매개변수로 받을까..?
         // handlePressSignTab의 기능을 다시한번 생각해보자

그후 직접 클릭이되는 S.Tab에 OnClick이벤트를 부여해줄것이다.
먼저 이벤트를 부여할 handlePressSignTab에 매개변수("SIGN-IN")를 넣어줄것이다

  • 주의할점

    ONclick이벤트의 함수는 콜백 함수의 형태로 들어가야만한다.
    onClick={handlePressSignTab("SIGN-IN")} -> 실행(x)
    onClick={() => handlePressSignTab("SIGN-IN")} -> 실행(o)

    만약 handlePressSignTab에 tab name이 아닌 event만 받고싶다면
    onClick에 함수만 넣어주면 된다. onClick={handlePressSignTab} 매개변수로 event가 들어오게 된다.

             const handlePressSignTab = (event) => {
                formState = tabName
            }


 위에 이벤트와 모든 조건을 맞추었으나 화면은 바뀌지 않는다 왜냐하면 리액트는 state를 통해 화면이 랜더링되기때문애
 변수를 useState를 통해 상태로 바꾸어줘야한다.

 state를 활용하기 전에 코드의 순회를 통해 중복을 없애보자
 먼저 배열    
        
```         const TAB_ARRAY = [
        {
            name: "SIGN-IN",
            isSelected: formState === "SIGN-IN"
        },
        {
            name: "SIGN-UP",
            isSelected: formState ===  "SIGN-UP"
        },
    ]

를 생성해준후

     {/* <S.Tab isSelected={formState === 'SIGN-IN'}
       onClick={() => handlePressSignTab("SIGN-IN")}>SIGN-IN</S.Tab>
        <S.Tab isSelected={formState === 'SIGN-UP'}
          onClick={() => handlePressSignTab("SIGN-IN")}
             >SIGN-UP</S.Tab> */}

전에 생성한 위 코드를 대신 map을 통해 순회를 시키며 위에 보이는 중복된 코드를 생략해보자

       {TAB_ARRAY.map((tab) => <S.Tab 
                $isSelected={tab.isSelected}
                onClick={()=>handlePressSignTab(tab.name)}
                >
                    {tab.name}
                </S.Tab>)}

로 간단하게 완성 시켜줄수있다.

나만의 코드 해석

먼저 TAB_ARRAY라는 배열을 생성했다.그 후 map을 통해 순회 시켜주었다.
순회를 시킴으로 <S.tab>을 배열 안의 갯수 만큼 생성해주었다. handlePressSignTab(tab.name) 의 tab.name은 배열안의 name: "SIGN-IN" 아니면 "SIGN-UP"일 것이다.
이렇게 배열을 통해 전달받은 tab.name이 다시 매개변수로 handlePressSignTab 함수의 tabName이라는 매개변수로 받아져
handlePressSignTab 함수의 기능 formState = tabname이라는 기능을 실행 시켜줄것이다.
그렇다면 $isSelected={tab.isSelected} 의 기능은?
// 위에서 정의 하였다.다시 정의 해보자

이제 배열이 추가 될때마다 S.css가 좀더 간편히 추가될것이다.

그리고 map 사용시 주의할점으로 항상 키값을 추가해주는것을 잊으면 안된다.
key = {tab.name}을 하게된다면 겹치게 되니 index를 활용하여
key = {tab.index}를 사용해주자


이제 Sign-In-Form css를 작성해볼것이다.

--공용 컴포넌트 만들기!

지금까지는 스타일 컴포넌트에 props를 전달해보았다 이제 실제 컴포넌트에 props를 전달하는법을 배워볼수있도록 하자

  1. props알고가기
  2. 구조분해할당
  3. 나머지 매개변수 연산자
   




    

    






  
profile
개발자 꿈나무

0개의 댓글