프론트엔드/React

[27] 리액트 동적스타일

반신욕좋아하는J 2022. 12. 8. 17:04
반응형

동적스타일

어떤 조건에 맞는 스타일속성을 지정해줄때가있다.

이런 동적인스타일을 적용시키는데에는 여러가지 방법이 존재하는데

크게 해당 요소에 인라인속성을줘서 주는방법이있고
미리 클래스에 스타일을 적용시킨다음에 해당조건에맞으면 클래스이름을 주거나 삭제시키는 방법으로 할수도있다.

import React, { useState } from "react";

import Button from "../../UI/Button/Button";
import "./CourseInput.css";

const CourseInput = (props) => {
  const [enteredValue, setEnteredValue] = useState("");
  const [isValid, setIsValid] = useState(true);

  const goalInputChangeHandler = (event) => {
    if (event.target.value.trim().length > 0) {
      setIsValid(true);
    }
    setEnteredValue(event.target.value);
  };

  const formSubmitHandler = (event) => {
    event.preventDefault();

    if (enteredValue.trim().length === 0) {
      setIsValid(false);
      return;
    }
    props.onAddGoal(enteredValue);
  };

  return (
    <form onSubmit={formSubmitHandler}>
      <div className={`form-control`}>
        **<label style={{ boderColor: !isValid ? "red" : "black" }}>**
          Course Goal
        </label>
        <input type="text" onChange={goalInputChangeHandler} />
      </div>
      <Button type="submit">Add Goal</Button>
    </form>
  );
};

export default CourseInput;

isValid 라는 state 값을 통해서 인라인 속성을 제어하고있다.

첫번째방법의 문제점은 인라인속성으로 주기때문에 다른스타일을 무시하고 적용될수있다는점이다.

두번째방법을 사용할때 리액트로 해당 상태를 관리하는 state 를 생성한뒤

state 를 통해서 클래스 이름을 동적으로 할당하여 관리를 할수있다.

코드를 확인해보자

import React, { useState } from "react";

import Button from "../../UI/Button/Button";
import "./CourseInput.css";

const CourseInput = (props) => {
  const [enteredValue, setEnteredValue] = useState("");
  const [isValid, setIsValid] = useState(true);

  const goalInputChangeHandler = (event) => {
    if (event.target.value.trim().length > 0) {
      setIsValid(true);
    }
    setEnteredValue(event.target.value);
  };

  const formSubmitHandler = (event) => {
    event.preventDefault();

    if (enteredValue.trim().length === 0) {
      setIsValid(false);
      return;
    }
    props.onAddGoal(enteredValue);
  };

  return (
    <form onSubmit={formSubmitHandler}>
      **<div className={`form-control ${!isValid ? "invalid" : ""}`}>**
        <label>Course Goal</label>
        <input type="text" onChange={goalInputChangeHandler} />
      </div>
      <Button type="submit">Add Goal</Button>
    </form>
  );
};

export default CourseInput;

isValid 라는 state 를 통해서 invalid 라는 클래스 이름을 추가하고있다.

해당 클래스에는 미리 css 스타일링을 적용한상태이다.

그런데 이런스타일들의 단점은 import 를 해당 파일에만 했다고해서 모듈화되 적용시킨 js 파일에서만 동작하는것이 아닌 , 모든 파일에 영향을 줄수있다.

그렇기때문에 프로젝트가 커지면 커질수록 , 다른사람이 같은 클래스네임을 작성했다면 해당 클래스 네임에도

스타일이 적용될수있다는 얘기다 .

이런 것들을 제어하기위해서 styled components 패키지 를 사용해보자 .

공식 페이지 에 들어가서 패키지 설치하는방법을 보고 따라해보자

https://styled-components.com/

npm 을 통해서 설치했다면 프로젝트내에서 사용할수있다.

먼저 import 를 해준뒤 사용해보자

import styled from 'styled-components';

import styled from "styled-components";

const Button = styled.button`
  font: inherit;
  padding: 0.5rem 1.5rem;
  border: 1px solid #8b005d;
  color: white;
  background: #8b005d;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
  cursor: pointer;

  &:focus {
    outline: none;
  }

  &:hover,
  &:active {
    background: #ac0e77;
    border-color: #ac0e77;
    box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
  }
`;

export default Button;

이런식으로 styled 의 메소드로 button 태그를 사용하여 아래에 스타일을 적용시켜 컴포넌트화 시켜 사용할수있다.

크롬브라우저의 개발자도구를 통해 styled-components 를 통해 생성한 태그를 보면 class 이름이 중복되지않게 적용된것을볼수있다.

이를통해서 다른곳에서 사용하더라도 클래스이름이 유니크하기때문에 중복적으로 사용할 일이 없어지게되고 ,

위 두가지 방법의 문제점을 해결할수있게된다.

CSS module

기존에 동적스타일을 지정 할때 클래스이름이 다른 어디선가 동일하게 사용된다면

해당 클래스에도 스타일이 적용되어 예기치않는 일들이 있어 문제가 된다 했다.

이는 styled-components 패키지에서 클래스이름을 유니크한값으로

지정해주는 것으로 그런 문제들을 해결했다.

하지만 한파일내에 스타일코드와 컴포넌트를 구성하는 코드들이 있기때문에

코드 가독성이 좋지않다고 생각하게되어 다른 방법을 배워보았다.

먼저 CSS module 은 파일이름을 [이름].module.css. 로 저장해야된다.

**import styles from "./CourseInput.module.css";**

그리고 해당하는 파일을 임의의 이름으로 임포트를 한뒤 해당 변수로 사용하면된다.

import React, { useState } from "react";

import Button from "../../UI/Button/Button";
import styles from "./CourseInput.module.css";

const CourseInput = (props) => {
  const [enteredValue, setEnteredValue] = useState("");
  const [isValid, setIsValid] = useState(true);

  const goalInputChangeHandler = (event) => {
    if (event.target.value.trim().length > 0) {
      setIsValid(true);
      console.log(isValid);
    }
    setEnteredValue(event.target.value);
  };

  const formSubmitHandler = (event) => {
    event.preventDefault();

    if (enteredValue.trim().length === 0) {
      setIsValid(false);
      return;
    }
    props.onAddGoal(enteredValue);
  };

  return (
    <form onSubmit={formSubmitHandler}>
      <div
        **className={`${styles["form-control"]} ${!isValid && styles.invalid}`}
      >**
        <label style={{ boderColor: !isValid ? "red" : "black" }}>
          Course Goal
        </label>
        <input type="text" onChange={goalInputChangeHandler} />
      </div>
      <Button type="submit">Add Goal</Button>
    </form>
  );
};

export default CourseInput;

기본적으로 styles를통해서 css 의 클래스들을 접근해서 사용할수있고 그릴이용해 조건을 걸어 동적스타일링을 할수도있다.

이렇게 className 을 지정하면 개발자도구에서 확인했을때 styled-components 와 동일하게 유니크한값을 임의로 지정하기때문에 문제를 해결하면서도 css 와 js 를 분리하여 코드가독성을 높일수있다.

반응형