반응형

과거 1년전쯔음에 만들었던 프로젝트가 있었는데 CRA로 생성한 프로젝트였다. 

 

Refactor를 위해 javascirpt에서 typescirpt로 바꾸고  React-query를 설치하려고 했는데 npm i 에서 에러가 났다. 

 

react-script 패키지가 'typescript@4.x'를 요구하는것이다. 

메세지에 --legacy-peer-deps옵션을 사용하는 방법이 있고 --force하는 방법도 있는데 두 방법 호환성을 억지로 맞추거나 아니면 보안에 취약한 선택인거 같아 첫째론 CRA github페이지에 들어가 보았다. 최신 commit이 작년이여서 방도를 몰라 GPT에게 물어본 결과 NEXT나 webpack 혹은 Vite를 사용하라는 결과가 나왔다. 

 

기존 작업해 둔 것들이 있고 데이터베이스를 따로 사용하지 않아 Next로 바꾸는 것은 아닌것 같고 webpack으로 설정하면 너무나도 많은 설정이 있어 복잡해질것을 우려가 되어 빠르고 업그레이드 할 수 있는 Vite로 해결하는 것이 옳다고 판단이 들어 Vite를 설치 했다.

https://ko.vitejs.dev/

 

Vite

Vite, 차세대 프런트엔드 개발 툴

ko.vitejs.dev

Install

npm install vite

 

vite 설치 후 프로젝트의 파일경로들을 조금 수정하고 몇가지 파일도 생성을 해주어야 한다. 일단 파일경로를 살펴보면

 

CRA로 생성한 index.html은 public 폴더에  생성되는데 이 파일을 프로젝트 ROOT에 옮겨준다.

다음은 index.html에 있는 내용을 수정해주어야하는데 public에 관련된 파일 경로 (%PUBLIC_URL%)작성을 지워준다.

또한 body tag안에 script를 추가해 react가 시작되는 파일을 불러와주어야한다.

폴더경로
========
|public/
-| img/
--| main/
---| horse_icon_16.png
-| favicon.ico
-| manifest.json
|src
.
.
.
========

html 내부
========
<link rel="icon" href="/img/main/horse_icon_16.png" />

<body>
    <div id="root"></div>
    <script type="module" src="/src/index.tsx"></script>
</body>

vite.config.ts

다음 단계는 vite 설정파일을 만들어주는 것이다. 파일이름은 vite.config.ts이며 root에 위치해야한다.

그리고 인텔리센스 설정을 해준다. https://ko.vitejs.dev/config/#config-intellisense

 

Vite

Vite, 차세대 프런트엔드 개발 툴

ko.vitejs.dev

그리고 vite에서 react를 사용할 수 있게 plugin을 지정해준다.

server host를 원하는 번호로 입력해준다. 프록시 , cors, headers 등을 더 알고 싶으면 위 링크.

import {defineConfig} from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
  },
});

 

Environment Variables

CRA에서 env를 사용하기 위해서는 root에 .env 파일 내부에 REACT_APP_**이라고 변수를 만들어주어서 스크립트 내부에 

process.env.REACT_APP_**라고 생성했었다. 하지만 vite에서는 process.env를 사용하기 위해서는 .env파일에 VITE_APP_***라고 생성해야며 사용시에는 import.meta.env.VITE_APP_***으로 사용되어야한다. 또한 typescript를 사용해 자동완성을 만들기 위해서는  src 폴더내에 vite-env.d.ts를 만들어 사용한다.

// src/vite-env.d.ts

/// <reference types="vite/client"/>

interface ImportMetaEnv {
  readonly VITE_APP_OPEN_API_ENCODING_KEY: string;
  readonly VITE_APP_API_KEY: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

 

728x90

'React > ReactJS' 카테고리의 다른 글

2023/07/27__ReactJS(5)  (0) 2023.07.27
2023/07/24__ReactJS(4)  (0) 2023.07.24
2023/07/21__ReactJS  (0) 2023.07.21
2023/07/20__ReactJS(3)  (0) 2023.07.20
2023/07/19__ReactJS(2)  (0) 2023.07.19
반응형

React Hook Form // https://react-hook-form.com/

 

React Hook Form - performant, flexible and extensible form library

Performant, flexible and extensible forms with easy-to-use validation.

react-hook-form.com

react hook form은 validation이나 에러, 이벤트 같은 필요한 기능들을 넣어서 적은 줄의 코드를 사용해 form을 만들 수 있게 해준다.

아래 코드는 기존 hoor form을 안쓰고 하는경우이다

"use client";
import {SyntheticEvent, use, useState} from "react";

export default function Form() {
  const [username, setUsername] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("")
  const [formErr, setFormErr] = useState("");
  const onUsernameChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
    const {
      currentTarget: {value},
    } = event;
    setUsername(value);
  };
  const onEmailChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
    const {
      currentTarget: {value},
    } = event;
    setEmail(value);
  };
  const onPasswordChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
    const {
      currentTarget: {value},
    } = event;
    setPassword(value);
  };
  const onSubmit = (event: SyntheticEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log(username, email, password);
    // validation codes..
        // validation codes..
            // validation codes..
                // validation codes..
                    // validation codes..
                        // validation codes..    // validation codes..
                        
  };
  return (
    <div>
      <form action="" onSubmit={onSubmit}>
        <input
          value={username}
          onChange={onUsernameChange}
          type="text"
          placeholder="Username"
          required
        />
        <input
          value={email}
          onChange={onEmailChange}
          type="email"
          placeholder="Email"
          required
        />
        <input
          value={password}
          onChange={onPasswordChange}
          type="password"
          placeholder="password"
          required
        />
        <input type="submit" value="submit"/>
      </form>
    </div>
  );
}

hook form을 사용하지 않게 되면 사용자가 html코드를 건드려 마음대로 설정할수 있다.

또한 좋은 form을 만들려다보면 스크립트 내에서의 validation을 검증하는 코드가 길어진다.

 

React Hook Form Install

npm install react-hook-form

 

How To Use?

1. register

첫번째로 해야할 것은 input을 state와 연결하는 것이다. 다음에 validation을 하고 다음에 err를 다룬다.

console.log(register)를 하게 되면 4가지를 사용할 수 있음을 볼 수 있다. name ,onBlur, onChange ,ref 이것들은 React에서 Input에 활용되는 attribute와 비슷하다.

"use client";

import {useForm} from "react-hook-form";

export default function Form() {
  const {register} = useForm();

  return (
    <div>
      <form>
        <input
          {...register("username")}
          type="text"
          placeholder="Username"
          required
        />
        <input
          {...register("email")}
          type="email"
          placeholder="Email"
          required
        />
        <input
          {...register("password")}
          type="password"
          placeholder="password"
          required
        />
        <input type="submit" value="submit" />
      </form>
    </div>
  );
}

 

2.  watch

"use client";

import {useForm} from "react-hook-form";

export default function Form() {
  const {register, watch} = useForm();
	console.log(watch())
	console.log(watch("email"))
    //원하는 것만 볼 수도 있다.
  return (
    <div>
      <form>
        <input
          {...register("username")}
          type="text"
          placeholder="Username"
          required
        />
        <input
          {...register("email")}
          type="email"
          placeholder="Email"
          required
        />
        <input
          {...register("password")}
          type="password"
          placeholder="password"
          required
        />
        <input type="submit" value="submit" />
      </form>
    </div>
  );
}

콘솔창을 열고 input에 값을 입력하면 register된 input의 값이 바로 변경하는것을 볼 수 있다.

3. validation

register의 두번째 인자로 validation Rule를 적을 수 있게 해준다.

"use client";

import {useForm} from "react-hook-form";

export default function Form() {
  const {register, watch} = useForm();
	console.log(watch())
  return (
    <div>
      <form>
        <input
          {...register("username",{
          required:true,
          })}
          type="text"
          placeholder="Username"
        />
        <input
          {...register("email",{
          required:"Email is Required",
          })}
          type="email"
          placeholder="Email"
        />
        <input
          {...register("password",{
          required:true,
          })}
          type="password"
          placeholder="password"
        />
        <input type="submit" value="submit" />
      </form>
    </div>
  );
}

4. handleSubmit

handleSubmit은 인자로 2개 또는 1개의 함수를 받을 것이다. 1개는 필수로 설정되어 있다.

첫번째 함수는 form이 유효할 때만 실행되는 함수

두번째 함수는 form이 유효하지 않을 때 실행되는 함수

"use client";
import {FieldErrors, useForm} from "react-hook-form";

interface ILoginForm {
  username: string;
  email: string;
  password: string;
}

export default function Form() {
  const {register, watch, handleSubmit} = useForm<ILoginForm>();
  console.log(watch());
  const onValid = (data: ILoginForm) => {
    console.log("OK");
  };
  const onInValid = (errors: FieldErrors) => {
    console.log(errors);
  };
  return (
    <div>
      <form onSubmit={handleSubmit(onValid, onInValid)}>
        <input
          {...register("username", {
            required: "Username is Required",
            minLength: 5,
          })}
          type="text"
          placeholder="Username"
        />
        <input
          {...register("email", {
            required: "Email is Required",
          })}
          type="email"
          placeholder="Email"
        />
        <input
          {...register("password", {
            required: "Password is Required",
            minLength: {
              message: "More Than 5",
              value: 5,
            },
          })}
          type="password"
          placeholder="password"
        />
        <input type="submit" value="submit" />
      </form>
    </div>
  );
}

 

5.formState & Others..

formState는 많은 걸 제공하는 객체인데 그중하나가 errors 이다.

errors로 validate error를 도출해낼수 있다. 

setValue는 이벤트를 통해 원하는 input에 값을 넣어줄 수 있다.

setError는 특정 필드에 대한 에러가 아니라 form에 대한 전체적인 에러를 얘기한다. 예를 들어 fetch를 통한 에러

reset은 submit을 동작하게 되면 input의 값들을 초기화하는 동작을 한다.

resetField는 특정 input값을 초기화 해준다

"use client";

import {FieldErrors, useForm} from "react-hook-form";

interface ILoginForm {
  username: string;
  email: string;
  password: string;
  errors?: string;
}
export default function Form() {
  const {
    register,
    watch,
    handleSubmit,
    formState: {errors},
    setValue,
    setError,
    reset,
    resetField,
  } = useForm<ILoginForm>({
    mode: "onBlur",
  });

  console.log(watch());

  const onValid = (data: ILoginForm) => {
    console.log("OK");
    setError("errors", {message: "backend is offline"});
    resetField("password");
  };
  const onInValid = (errors: FieldErrors) => {
    console.log(errors);
    reset();
  };

  return (
    <div>
      <form onSubmit={handleSubmit(onValid, onInValid)}>
        <input
          {...register("username", {
            required: "Username is Required",
            minLength: {
              message: "more than 5",
              value: 5,
            },
          })}
          type="text"
          placeholder="Username"
          className={`${Boolean(errors.username) ? "bg-red-400" : ""} 
           `}
        />
        <button
          type="button"
          onClick={() => {
            setValue("username", "hihihi");
          }}
        >
          push
        </button>
        <p>{errors.username?.message}</p>
        <input
          {...register("email", {
            required: "Email is Required",
            validate: {
              notGmail: (value) =>
                !value.includes("@gmail.com") || "Gmail is not allowed",
            },
          })}
          type="email"
          placeholder="Email"
        />
        {errors.email?.message}
        <input
          {...register("password", {
            required: "Password is Required",
            minLength: {
              message: "More Than 5",
              value: 5,
            },
          })}
          type="password"
          placeholder="password"
        />
        {errors.password?.message}
        <input type="submit" value="submit" />
        {errors.errors?.message}
      </form>
    </div>
  );
}

 

728x90

'React > React Hook Form' 카테고리의 다른 글

2023/08/31__React(ReactHookForm)  (2) 2023.08.31
반응형

React-Hook-Form

React Hook Form라이브러리를 사용하면 따로 이벤트 헨들러, state를 만들 필요가 없다.

// 기존

export default function Mainpage() {
  const [val, setVal] = useState("");
  const onChange = (event: React.FormEvent<HTMLInputElement>) => {
    const {
      currentTarget: {value},
    } = event;
    setVal(value);
  };
  const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
     console.log("submit")
  };
  return (
    <div>
      <h1>React / Recoil / StyledComponent / TypeScript / To Do List</h1>
      <form onSubmit={onSubmit}>
        <input type="text" value={val} onChange={onChange} />
        <button>Add</button>
      </form>
    </div>
  );
}

1-1. register()

register 함수를 사용하면 onChange 이벤트 핸들러, props, state 가 필요가 없다.

register 함수에는 

  • name
  • onChnage
  • onBlur
  • ref

가 내포되어 있다.  react input의 attribute라고 생각되면 됨

1-2. watch()

watch는 form의 입력값들의 변화를 관찰 할 수 있게 해주는 함수

1-3. handleSubmit( onValid(required), onInValid(optional))

validation을 담당함 .  handleSubmit에는 2개의 인자를 받는데 하나는 데이터가 유효할 때 호출되는 함수

다른 하나는 실패했을 때 호출 되는 함수

1-4.formState

console.log(formState.errors)를 하게 되면 해당부분에 떤 에러가 났는지 디버깅 할수 있다.

interface IFormData {
  todo: string;
  email: string;
  errors: {
    email: {
      message: string;
    };
  };
}
export default function Mainpage() {
  const {
    register,
    watch,
    handleSubmit,
    formState: {errors},
  } = useForm<IFormData>();
  const onValid = (data: any) => {
    console.log(data);
  };

  return (
    <div>
      <h1>React / Recoil / StyledComponent / TypeScript / To Do List</h1>
      <form onSubmit={handleSubmit(onValid)}>
        {/* // register안에 required를 작성해 html의 소스코드를 보호할수 있다. */}
        <input
          {...register("todo", {
            required: true,
            minLength: {
              value: 5,
              message: "length is too short",
            },
          })}
          type="text"
          placeholder="Write a to do"
        />
        <input
          {...register("email", {
            required: "emai is required",
            minLength: 5,
            pattern: {
              value: /^[A-Za-z0-9._-]*@[A-za-z0-9]*\.[a-zA-Z]{2,3}$/,
              message: "only email",
            },
          })}
          type="email"
          placeholder="Write Email"
        />
        <span>{errors?.email?.message}</span>
        <button>Add</button>
      </form>
    </div>
  );
}

2. Custom Validation

  const onValid = (data: IFormData) => {
    if (data.pw !== data.pw1)
      setError("pw1", {message: "pw are not same"}, {shouldFocus: true});
    setError("extraError", {message: "server offline"});
  };
  
  // 코드 생략
  
   <input
          {...register("name", {
            required: true,
            minLength: {
              value: 5,
              message: "length is too short",
            },
            validate: {
              badName: (value) =>
                value.includes("fuck") ? "bad word is not allowd" : true,
            },
          })}
          type="text"
          placeholder="Write a name"
        />
        <span>{errors?.name?.message}</span>

 

728x90

'React > React Hook Form' 카테고리의 다른 글

React Hook Form  (0) 2023.11.15
반응형

React Query 공식 홈은 -> 여기다   TanStack Query

 

먼저 npm i @tanstack/react-query 을 해준다.

다음으로

index.tsx에 가서

import {QueryClient, QueryClinetProvider} form '@tanstack/react-query'

const queryClient = new QueryClient()

function App(){
	retrun (
     <QueryClientProvider client={queryClient}>
      <Todos />
    </QueryClientProvider>
  )
}

작업을 해준다.

 

Api가 있는 template 파일의 문장을 토대로 스크립트 파일을 하나 만든다

// api.ts

export const functionName = async()=>{
	return fetch('').then((response)=>response.json())
}

 

후에

Api가 있는 template 파일로가서 useEffect가 있는 문장을 없애주고

import {api} from './api.ts'
import {useQuery} from '@tanstack/react-query'


export default FunctionName (){
	const {isLoading, data} = useQuery(['keyName'], functionApi)
    // 비동기 방법
    const {isLoading, data} = useQuery(['keyName'], async () => {
    	const data = await functionApi
        return data
        },
        //5초마다 refetch
        {
        	refetchInterval:5000;
         }
        )
	return(
    <div>
    {isLoading ? <span> loading </span> : data.map()//문장 구성}
    </div>
    )
}
728x90
반응형

Connect Typescript with styled-components

1. 설치

npm install @types/styled-components

2.  선언파일 만들기 (Create a declarations file)

src폴더 안에 styled.d.ts 생성 후 styled-components의 공식문서에서 선언파일 만드는 방법을 찾아 붙이기

//styled.d.ts

// import original module declarations
import "styled-components";

// and extend them!
declare module "styled-components" {
  export interface DefaultTheme {
    textColor: string;
    bgColor: string;
    btnColor: string;
  }
}
//theme.ts
import {DefaultTheme} from "styled-components/dist/types";

export const lightTheme: DefaultTheme = {
  bgColor: "white",
  textColor: "black",
  btnColor: "teal",
};
export const darkTheme: DefaultTheme = {
  bgColor: "black",
  textColor: "white",
  btnColor: "tomato",
};
//App.tsx

import React, {useState} from "react";
import styled from "styled-components";

const Btn = styled.button`
  background-color: ${(props) => props.theme.btnColor};
`;

function App() {
  const [val, setVal] = useState("");
  const onChange = (event: React.FormEvent<HTMLInputElement>) => {
    /** event의 타입을 주기위해서는 위와 같이 작성해야하는데 저것을 찾기 위해서는 어떤곳에서 이벤트가 이루어졌는지 생각해보면 쉽게 다가갈수 있음 혹은
     * 공식문서나 구글링을 통해 찾는 걸 추천함 */
    // console.log(event.currentTarget.value);
    /** 또한 보통 자바스크립트 같은 경우엔 target이라고 작성하는데 타입스크립트와 리액트를 같이 사용하는데 있어서 currentTarget으로 작성해야한다.*/
    const {
      currentTarget: {value},
    } = event;
    setVal(value);
  };

  const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log(val);
  };
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input
          value={val}
          onChange={onChange}
          type="text"
          placeholder="UserName"
        />
        <button>Log In</button>
      </form>
      <Btn>눌러뽕</Btn>
    </div>
  );
}

export default App;

 

Styled-Components 의 Style - Reset 하기

  • npm i styled-reset
  • 아니면 styled-reset의 깃에 들어가 src/index.ts를 복붙하면됨
import React from "react";
import styled, {createGlobalStyle} from "styled-components";
import Mainpage from "./views/Mainpage";

const GlobalStyle = createGlobalStyle`
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+KR:wght@100;200;300;400;500;600;700&display=swap');
  html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, menu, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
main, menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, main, menu, nav, section {
  display: block;
}
/* HTML5 hidden-attribute fix for newer browsers */
*[hidden] {
    display: none;
}
body {
  line-height: 1;
  font-family: 'IBM Plex Sans KR', sans-serif;
  color: ${(props) => props.theme.textColor};
  background-color: ${(props) => props.theme.bgColor};
}
menu, ol, ul {
  list-style: none;
}
blockquote, q {
  quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}
*{
  box-sizing:border-box;
}
a{
  text-decoration:none;
}
`;

const Wrapper = styled.div`
  display: flex;
`;
function App() {
  return (
    // Fragment - ghost component
    <>
      <GlobalStyle />
      <Wrapper>
        <Mainpage />
      </Wrapper>
    </>
  );
}

export default App;
728x90

'React > Styled-Components' 카테고리의 다른 글

2023/08/24__Styled-Components(2)  (0) 2023.08.24
2023/08/23__Styled-Components(1)  (0) 2023.08.23
반응형

1. Animation 과 Pseudo 선택자

//animation 효과를 주기위서는 keyframes를 불러와야한다.
import styled, {keyframes} from "styled-components";

const Wrapper = styled.div`
  display: flex;
`;

const rotateAnimation = keyframes`
0%{
transform:rotate(0deg);
border-radius:0px
}
50%{
  border-radius:100px;
}
100%{
transform:rotate(360deg);
border-radius:0px
}
`;

const Emoji = styled.span`
  font-size: 50px;
`;

const Box = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  width: 200px;
  height: 200px;
  background-color: tomato;
  animation: ${rotateAnimation} 3s linear infinite;
  span {
    font-size: 20px;
    &:hover {
      font-size: 60px;
      transition: ease-in-out 1s;
    }
    // SCSS와 비슷하다
  }
`;
const Box2 = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  width: 200px;
  height: 200px;
  background-color: tomato;
  animation: ${rotateAnimation} 3s linear infinite;

  ${Emoji}:hover {
    font-size: 100px;
    transition: ease-in-out 1s;
  }
`;

function App() {
  return (
    <Wrapper>
      <Box>
        <span>😀</span>
      </Box>
      <Box2>
        <Emoji>🥸</Emoji>
      </Box2>
      <Emoji>🥸</Emoji>
    </Wrapper>
  );
}

export default App;

2. Themes

다크모드를 하기 위한 첫단계

각 Theme에는 같은 오브젝트의 명이 담겨져 있어야한다고 생각하고 작업에 임하라.

//index.js
import React from "react";
import ReactDOM from "react-dom/client";
import {ThemeProvider} from "styled-components";
import App from "./App";

const darkTheme = {
  textColor: "whitesmoke",
  backgroundColor: "#222",
};
const lightTheme = {
  textColor: "#222",
  backgroundColor: "whitesmoke",
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <ThemeProvider theme={darkTheme}>
      <App />
    </ThemeProvider>
  </React.StrictMode>
);



//App.js
//animation 효과를 주기위서는 keyframes를 불러와야한다.
import styled, {keyframes} from "styled-components";

const Wrapper = styled.div`
  display: flex;
  background-color: ${(props) => props.theme.backgroundColor};
`;

const Title = styled.h1`
  color: ${(props) => props.theme.textColor};
`;
function App() {
  return (
    <Wrapper>
      <Title>HELLO</Title>
    </Wrapper>
  );
}

export default App;

 

728x90

'React > Styled-Components' 카테고리의 다른 글

2023/08/25__Styled-Components with Typescript(3)  (0) 2023.08.25
2023/08/23__Styled-Components(1)  (0) 2023.08.23
반응형

Styled-Components

React에서 style을 주기위한 방법은 몇가지가 있다.

  • 첫 번째로 직접 엘리멘탈에 스타일을 주는방법
return(
	<div style={{backgroundColor:'red'}}>
    	<h1>hello</h1>
    </div>
)
  • 두 번째로 CSS 모듈 파일을 만든다
  • 파일이름.module.css
import styles from '파일이름.module.css'

export default function 컴포넌트이름 (){
	return (
    	<div className={styles.hello}>
        	<h1 className={styles.text}> hello </h1>
        </div>
    )
}


/** 
파일이름.module.css

.hello{
background-color:teal;
}

.text {
color:white;
}

*/
  • 세 번째로는 프레임워크를 사용하는것
  • 네 번째로는 stlyed-component라이브러리를 사용

설치

리액트 프로젝트 생성 후

npm i styled-components
import styled from 'styled-compoenets'

//백틱에 스타일이 들어가야 한다.
const SayHello = styled.h1`
	background-color:teal;
	color:red;
    width:100px;
    height:100px
    `;
    
//props로도 스타일을 줄 수 있다.    
const SayMeetYou = styled.div`
	background-color: ${(props)=>props.bgColor};
    width:100px;
    heigth:100px;
    `;
    
// SayMeetYou의 요소를 그대로 사용하며 border-radius의 값을 추가하여 사용할 수 있다.
const SayBye = styled(SayMeetYou)`
    border-radius:50px;
    `;


// 예로 버튼태그에 스타일을 주었는데 링크테그에도 똑같은 스타일을 주고 싶을 때 사용하는 방법
const Btn = styled.button`
	border: 0;
    border-radius: 25px
    background-color: tomato:
    color:white;
    `;
    
//어트리뷰트 값도 지정해줄 수 있다.
const Input = styled.input.attrs({required:true, minLength:'10'})`
	background-color: cornflowerblue;
`;

export default function App (){
  return(
   <div>
    <div
     style={{ backgroundColor:'teal', width:100, height:100 }}>
				<h1> hello </h1>
    </div>
    <div>
     <SayHello> hello </SayHello>
    </div>
    <SayMeetYou bgColor={"orange"}}></SayMeetYou>
    <SayBye bgColor={"Yellow"}}></SayBye>
    <Btn>Click me</Btn>
    // Btn 스타일일을 쓰고 싶지만 링크로써 사용하고 싶다면 as라는 props를 줘서 원하는 html을 부여할 수 있다.
    <Btn as='a' href='URL LINK'>Click me</Btn>
    <Input/>
   </div>
  )
}

 

728x90

'React > Styled-Components' 카테고리의 다른 글

2023/08/25__Styled-Components with Typescript(3)  (0) 2023.08.25
2023/08/24__Styled-Components(2)  (0) 2023.08.24
반응형

Redux

Redux

  • 상태 중앙 관리도구
  • 개발복잡성을 낮춰 줌

주요 키워드

액션(Action)

  • 상태에 변화가 필요할 때 호출
  • 객체 형식으로 사용
  • type 속성 필수
{
 type:"CLASS_ROOM",
 student:{
  id:0,
  name:"김철수"
 },
 teacher: "홍길동"
}

액션 생성함수(Action Creator)

  • 액션 생성
  • 파라미터를 가져와 객체형태로 변환
  • 컴포넌트에서 쉽게 액션을 발생시키기 위해 사용
export function addClassRoom(data){
  return{
   type: "CLASS_ROOM",
   data
  }
}

리듀서(Reducer)

  • 변화를 발생시키는 함수
  • stated와 action 두가지  파라미터 사용
  • 현재의 상태와 전달받은 액션을 참고하여 새로운 상태반환
  • 반드시 기존 state를 그대로 반환하도록 작성
  • 여러개의 작은 리듀서(서브리듀서)를 만들고 이를 합쳐 루트 리듀서(Root Reducer)로 작성 가능
function reducer(state, action){
 //상태 업데이트 로직
 return alteredState;
}

스토어(Store)

  • 애플리케이션당 하나의 스토어 사용
  • 현재의 앱 상태, 리듀서, 내장함수포함
  • 제공 메소드: .getState(), .dispatch(), .subscribe()

디스패치(dispatch)

  • 액션을 발생시키는 스토어 내장함수
  • 파라미터로 액션전달
  • dispatch함수 호출 시 스토어는 리듀서 함수 실행

구독(subscribe)

  • 스토어 내장 함수
  • 함수형태의 값을 파라미터로 사용
  • subscribe 함수에 특정함수를 전달하면 액션이 디스패치 되었을 때 마다 전달해준 함수가 호출

컴포넌트 (템플릿, 뷰) => 디스패치 (변경요청) => 액션(스토에게 어떤걸 바꿔야하는 지 알려줌) => 리듀서 (어떻게 해야하는지)  

(1의 템플릿에서 바뀐 값을 2,3 의 템플릿에 "바로" 자동으로 사용하게 하고 싶으면 구독을 추가한다)

 

리덕스의 3가지 규칙

하나의 애플리케이션 안에는 하나의 스토어 사용

  • 애플리케이션 상태는 모두 한 곳에서 집중관리(동기화 필요 없음)
  • 여러개의 스토어를 사용하는 것은 사실 가능( 권장 하지 않음)

상태는 불변 데이터(읽기전용)

  • 내부적으로 데이터가 변경되는 것을 감지하기 위하여 shallow equality 검사
  • 기존의 상태는 보전하고 새로운 상태를 생성하여 업데이트 하는 것이 유리
  • 액션만 상태 교체 요청가능(예측가능)

리듀서(함수)를 통해 상태의 최종값만 설정(단순화)

  • 리듀서 : 변화를 일으키는 함수,  순수한 함웃여야 함
  • 상태와 액션을 전달 받아 '이전 상태'를 다음 상태'로 교체 한 후 반환
  • 전달 받은 매개변수 state, action 변형불가
  • 네트워킹(API호출 <- 비동기 통신) 또는 라우팅 변경 불가
  • 반드시 반환 값은 새로운 상태 (state) 이어야 함

Store 생성(src>store.js)

중앙 상태 관리를 위한 store 생성

  • [src] 폴더에 store.js파일 생성
  • 또는 [src] - [store] - index.js

createStore함수

  • 첫번째 인자에 반드시 함수 호출(reducer)

reducer함수

  • reducer함수는 2개의 인자 사용(state,action)
  • state-사용할 state값
  • action
  •   ㄴ 상태에 변화를 일으키는 함수
  •   ㄴ 현재의 상태와 액션을 인자로 받아 새로운 상태로 업데이트
  • 반드시 state를 return

dispatch

  • 액션을 처리해 상태를 업데이트
  • 액션을 발새이켜주는 함수

store 생성

import {createStore} from 'redux'

export default createStore(function(state,action) {
 if(state === undefined){
   return {number:0}
 }
 if(action.type === 'INCREMENT'){
   return{...state, number:state.number + action.size}
 }
 return state;
})
728x90

+ Recent posts