본문 바로가기

JavaScript/React.js

리액트-1 (데이터 변경 감지해 UI를 동적으로 렌더링하는 엔진)

728x90
반응형

https://reactjs-kr.firebaseapp.com/docs/installation.html

기존의 뷰 프로세스 [CSR]

1. 요청 -> view(html) -> 화면을 전달하면 브라우저가 렌더링 [전체 변경]

2. view -> 자바스크립트의 비동기 요청 -> ajax를 통해 부분 변경-> json으로 응답 -> 응답받은 데이터를 이용해 렌더링 [부분 변경]

3. 복잡한 화면일수록 부분 변경이 어렵다. [성능과 구현 측면에서]

[SSR]

-> 부분변경 x -> ajax -> html -> 그림그리기

리액트

: ajax -> 데이터 변경감지 -> UI가 자동 업데이트 [옵저버 패턴]

*npm, npx

(1) npm 프로젝트별로 라이브러리 관리 / 모든 프로젝트가 공유하도록 사용도 가능 (여러 버전 사용 불가능 -> 단일 버전만 가능)

(2) npx 라이브러리 존재시 공유 -> 실행 후, 삭제

npx create-react-app my-app

cd my-app
npm start

ESLint / Prettier / ReactJs code snippets

prettier 설정

{
    "singleQuote": false,
    "semi": true,
    "tabWidth": 2,
    "trailingComma": "all",
    "printWidth": 80
}

1) 실행 과정 - index.html을 구동 시키기 위한 과정 = SPA(Single Page Applicaiton)

-> a태그 사용불가 (클릭할 때 브라우저가 해당 URL로 이동하면서 전체 페이지를 다시 로드하기 때문에)

[ 태그 사용을 제한하는 이유는 페이지 리로드로 인한 성능 저하와 상태 유실을 방지

대신, 자바스크립트 기반 라우팅 라이브러리(React Router)를 사용하여 URL 변경과 동적 콘텐츠 로딩을 처리]

더보기

import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';

function App() {
  return (
    <Router>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
      </nav>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
      </Switch>
    </Router>
  );
}

package.json

"scripts": {

"start": "react-scripts start",

"build": "react-scripts build",

"test": "react-scripts test",

"eject": "react-scripts eject"

},

-> index.tsx 실행

index.tsx

const root = ReactDOM.createRoot(

document.getElementById('root') as HTMLElement

);

root.render(

<React.StrictMode>

</React.StrictMode>

);

-> rendering

public/index.html

* Document 클래스 메서드

1) queryselector-> 선택자 '#'은 ID

2) getelementbyid-> ID요소 가져오기


2) jsx 문법

*tsx -> js로 변환 후 렌더링

: JavaScript 및 TypeScript 코드에서 HTML과 같은 구문을 사용하여 UI 구성 요소를 작성할 수 있게 하는 확장 문법

-> js에 html 주입

[React.js (라이브러리) / Next.js (프레임워크)]

타입 라이브러리 프레임워크
기본 렌더링 방식 클라이언트 사이드 렌더링(CSR) 서버사이드 렌더링(SSR) 및 정적 사이트 생성(SSG) 지원
라우팅 React Router 등 외부 라이브러리 필요 파일 기반 라우팅 지원
데이터 페칭 클라이언트 사이드에서 주로 처리 SSR, SSG, 클라이언트 사이드 모두 지원
API 라우트 없음 (외부 서버 필요) 내장된 API 라우트 지원
설치 및 설정 필요한 라이브러리들을 별도로 설정 기본 설정이 포함된 일체형 프레임워크
코드 스플리팅 Webpack 등 설정 필요 기본 제공
CSS 지원 외부 라이브러리 사용 (예: styled-components, Emotion) 기본적으로 CSS 및 Sass 지원

jsx: js에 html 넣는 방법 -> function App() { JSX 문법 }

function App() {
  return (
    //1)
    // <div className="App">
    //   <header className="App-header">
    //     <img src={logo} className="App-logo" alt="logo" />
    //     <p>
    //       Edit <code>src/App.tsx</code> and save to reload.
    //     </p>
    //     <a
    //       className="App-link"
    //       href="https://reactjs.org"
    //       target="_blank"
    //       rel="noopener noreferrer"
    //     >
    //       Learn React
    //     </a>
    //   </header>
    // </div>

    <div>
      Hello
    </div>
  );
}

(1) react는 하나의 태그만 리턴 -> 하나의 태그 안에 모두 삽입

-> return 시에 하나의 Dom만 리턴

(2) 변수의 위치 (변수 스코프)

-> 변수 선언 : let/const만 사용 [var의 스코프는 일반적으로 예상가능하지 않음]

(3) if사용 불가 -> 삼항연산자로 대신 가능 (조건?true:false)

-> '==' : 값 동등 체크, '===' : 값+타입 동등 체크

(4)조건부 렌더링 참일때만 '&&' (조건 && true)

-> 참일때만 출력

(5) 리턴이 한줄일 떄와 한줄 초과일 때 괄호 유무의 차이

-> 한줄일 때는 괄호 생략 가능

(6) js에서 변수에 선언만 할 경우 -> undefined (NULL이 아님)

(7) css 디자인

- 내부

- 외부

- 라이브러리 사용 (부트스트랩, component-style)


3) useState

: 상태값 변경시 렌더링 -> 상태값이 아니면 변경되어도 화면상에선 바뀌지않음

더보기

주의사항

  1. 비동기 상태 업데이트: setState 함수는 비동기로 작동할 수 있으며, 즉시 상태가 업데이트되지 않을 수 있습니다. 따라서 상태가 즉시 반영되지 않는 경우가 있을 수 있습니다.
  2. 이전 상태 기반 업데이트: 상태 업데이트가 이전 상태 값에 의존하는 경우, 콜백 함수를 사용하는 것이 좋습니다.
  3. jsxconst increment = () => { setCount(prevCount => prevCount + 1); };
  4. 코드 복사
  5. 객체 상태 업데이트: 상태가 객체인 경우, 전체 객체를 복사하고 수정해야 합니다.
    • ...prevUser: 이전 상태를 복사합니다.
    • { ...prevUser, name: 'Jane' }: 복사한 상태에 name 속성을 변경합니다.
  6. jsxconst [user, setUser] = useState({ name: 'John', age: 30 }); const updateName = () => { setUser(prevUser => ({ ...prevUser, name: 'Jane' })); };
  7. 코드 복사

요약

  • useState 훅은 상태 값을 관리하는 데 사용됩니다.
  • useState 훅은 현재 상태 값을 읽는 변수와 상태 값을 업데이트하는 함수를 반환합니다.
  • 상태 값을 업데이트할 때는 set 접두어를 사용하는 함수(setCount, setUser 등)를 호출합니다.
  • 상태 업데이트는 비동기로 작동할 수 있으며, 이전 상태에 기반한 업데이트는 콜백 함수를 사용하는 것이 좋습니다.

4) sub 컴포넌트

React 컴포넌트의 종류와 이에 대한 약어들은 다양하며, 주로 코드 템플릿이나 스니펫에서 사용됩니다. 여기에 각 컴포넌트의 종류와 해당 약어들을 소개합니다.

함수형 컴포넌트 (Functional Components)

  1. React Stateless Component (RSC)
    • 상태를 관리하지 않는 함수형 컴포넌트입니다.
    import React from 'react';
    
    const RSC = () => {
      return <div>Hello, World!</div>;
    };
    
    export default RSC;
  2. React Stateless Component with Props (RCSP)
    • props를 받아 렌더링하는 상태가 없는 함수형 컴포넌트입니다.
    import React from 'react';
    
    const RCSP = (props) => {
      return <div>{props.message}</div>;
    };
    
    export default RCSP;
  3. React Functional Component (RFC)
    • 기본적인 함수형 컴포넌트를 의미합니다.
    import React from 'react';
    
    const RFC = () => {
      return <div>Hello, World!</div>;
    };
    
    export default RFC;
  4. React Functional Component with Props (RFCP)
    • props를 사용하는 함수형 컴포넌트입니다.
    import React from 'react';
    
    const RFCP = ({ message }) => {
      return <div>{message}</div>;
    };
    
    export default RFCP;

클래스형 컴포넌트 (Class Components)

더보기

  1. React Class Component (RCC)
    • 상태와 생명주기 메서드를 사용할 수 있는 클래스형 컴포넌트입니다.
    import React, { Component } from 'react';
    
    class RCC extends Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0,
        };
      }
    
      render() {
        return (
          <div>
            <p>{this.props.message}</p>
            <p>Count: {this.state.count}</p>
          </div>
        );
      }
    }
    
    export default RCC;
  2. React Class Component with Props (RCCP)
    • props를 사용하는 클래스형 컴포넌트입니다.
    import React, { Component } from 'react';
    
    class RCCP extends Component {
      render() {
        return <div>{this.props.message}</div>;
      }
    }
    
    export default RCCP;
  3. React Pure Component (RPC)
    • PureComponent를 상속받아 shouldComponentUpdate를 자동으로 구현하는 클래스형 컴포넌트입니다.
    import React, { PureComponent } from 'react';
    
    class RPC extends PureComponent {
      render() {
        return <div>{this.props.message}</div>;
      }
    }
    
    export default RPC;

Hook 기반 컴포넌트

  1. React Hook Component (RHC)
    • Hook을 사용하는 함수형 컴포넌트입니다.
    import React, { useState } from 'react';
    
    const RHC = () => {
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>Count: {count}</p>
          <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
      );
    };
    
    export default RHC;
  2. React Hook Component with Props (RHCP)
    • Hook과 props를 사용하는 함수형 컴포넌트입니다.
    import React, { useState } from 'react';
    
    const RHCP = ({ initialCount }) => {
      const [count, setCount] = useState(initialCount);
    
      return (
        <div>
          <p>Count: {count}</p>
          <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
      );
    };
    
    export default RHCP;

고차 컴포넌트 (Higher-Order Components)

  1. React Higher-Order Component (HOC)
    • 다른 컴포넌트를 감싸는 컴포넌트입니다.
    import React from 'react';
    
    const withEnhancement = (WrappedComponent) => {
      return class extends React.Component {
        render() {
          return <WrappedComponent {...this.props} />;
        }
      };
    };
    
    export default withEnhancement;

컨텍스트 기반 컴포넌트

  1. React Context Provider (RCP)
    • Context API의 Provider를 사용하는 컴포넌트입니다.
    import React, { createContext, useState } from 'react';
    
    export const MyContext = createContext();
    
    const RCP = ({ children }) => {
      const [value, setValue] = useState('default value');
    
      return (
        <MyContext.Provider value={{ value, setValue }}>
          {children}
        </MyContext.Provider>
      );
    };
    
    export default RCP;
  2. React Context Consumer (RCC)
    • Context API의 Consumer를 사용하는 컴포넌트입니다.
    import React from 'react';
    import { MyContext } from './RCP';
    
    const RCC = () => {
      return (
        <MyContext.Consumer>
          {({ value, setValue }) => (
            <div>
              <p>{value}</p>
              <button onClick={() => setValue('new value')}>Change Value</button>
            </div>
          )}
        </MyContext.Consumer>
      );
    };
    
    export default RCC;

이와 같이 다양한 유형의 React 컴포넌트가 있으며, 각 유형의 컴포넌트는 특정 목적과 사용 사례에 맞게 설계되었습니다. 이러한 약어들은 개발자들이 코드 템플릿을 빠르게 생성하고, 코드의 가독성을 높이는 데 도움을 줍니다.

* push는 불변

-> 레퍼런스 변경 : filter, map, concat, slice, 정규연산자


Hooks, Flux패턴 , Redux 예시

1. Hooks

사용 예시: 간단한 상태 관리와 부수 효과 처리

  • 예제: 사용자 입력 폼 관리
import React, { useState, useEffect } from 'react';

function UserForm() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  useEffect(() => {
    console.log('Name or email changed');
  }, [name, email]);

  return (
    <div>
      <input 
        type="text" 
        value={name} 
        onChange={(e) => setName(e.target.value)} 
        placeholder="Name"
      />
      <input 
        type="email" 
        value={email} 
        onChange={(e) => setEmail(e.target.value)} 
        placeholder="Email"
      />
      <p>Name: {name}</p>
      <p>Email: {email}</p>
    </div>
  );
}

export default UserForm;

설명: 여기서는 useState를 사용하여 간단한 상태(이름과 이메일)를 관리하고, useEffect를 사용하여 상태 변경 시 부수 효과를 처리합니다. 이 패턴은 단일 컴포넌트 내에서 간단한 상태 관리에 적합합니다.

2. Redux에서 사용하는 Flux 패턴

사용 예시: 복잡한 애플리케이션의 데이터 흐름 관리를 위한 정형화된 패턴

  • 예제: 기본적인 Flux 패턴의 구조
// actions.js
export const addAction = (item) => ({
  type: 'ADD_ITEM',
  payload: item,
});

// dispatcher.js
import { Dispatcher } from 'flux';
export const AppDispatcher = new Dispatcher();

// store.js
import { EventEmitter } from 'events';
import { AppDispatcher } from './dispatcher';

let items = [];

class ItemStore extends EventEmitter {
  getItems() {
    return items;
  }

  addItem(item) {
    items.push(item);
    this.emit('change');
  }
}

const store = new ItemStore();

AppDispatcher.register((action) => {
  switch (action.type) {
    case 'ADD_ITEM':
      store.addItem(action.payload);
      break;
    default:
      break;
  }
});

export default store;

// view.js
import React, { useState, useEffect } from 'react';
import store from './store';
import { addAction } from './actions';
import { AppDispatcher } from './dispatcher';

function ItemList() {
  const [items, setItems] = useState(store.getItems());

  useEffect(() => {
    store.on('change', () => {
      setItems(store.getItems());
    });
  }, []);

  const addItem = () => {
    AppDispatcher.dispatch(addAction('New Item'));
  };

  return (
    <div>
      <ul>
        {items.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
      <button onClick={addItem}>Add Item</button>
    </div>
  );
}

export default ItemList;

설명: Flux 패턴을 사용하여 액션, 디스패처, 스토어, 뷰의 구조를 구성합니다. 이 패턴은 상태와 관련된 모든 변경 사항을 체계적으로 관리하여 복잡한 애플리케이션의 데이터 흐름을 예측 가능하게 합니다.

3. Redux

사용 예시: 중앙 집중화된 상태 관리와 비동기 작업 처리

  • 예제: Todo 애플리케이션
// actions.js
export const ADD_TODO = 'ADD_TODO';
export const addTodo = (text) => ({
  type: ADD_TODO,
  payload: text,
});

// reducers.js
import { ADD_TODO } from './actions';

const initialState = {
  todos: [],
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TODO:
      return {
        ...state,
        todos: [...state.todos, action.payload],
      };
    default:
      return state;
  }
};

export default rootReducer;

// store.js
import { createStore } from 'redux';
import rootReducer from './reducers';

const store = createStore(rootReducer);

export default store;

// TodoList.js
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addTodo } from './actions';

function TodoList() {
  const [input, setInput] = useState('');
  const todos = useSelector((state) => state.todos);
  const dispatch = useDispatch();

  const handleAddTodo = () => {
    dispatch(addTodo(input));
    setInput('');
  };

  return (
    <div>
      <input 
        type="text" 
        value={input} 
        onChange={(e) => setInput(e.target.value)} 
        placeholder="Add todo"
      />
      <button onClick={handleAddTodo}>Add Todo</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>{todo}</li>
        ))}
      </ul>
    </div>
  );
}

export default TodoList;

설명: Redux를 사용하여 중앙 집중화된 상태 관리와 액션 및 리듀서를 통해 상태 변경을 예측 가능하게 합니다. Redux의 미들웨어를 활용하여 비동기 작업을 처리할 수 있습니다.

사용하는 이유

  • Hooks로 간단한 컴포넌트 상태와 부수 효과를 관리하고,
  • Redux로 중앙 집중화된 상태 관리와 비동기 작업을 처리합니다.
    • Flux 패턴으로 데이터 흐름을 체계적으로 관리
    • 모든 컴포넌트가 props 없이 state를 직접 사용(읽기) 가능
    • state에 대한 의미있는 메서드를 미리 정의

이러한 조합은 애플리케이션의 규모와 복잡성에 따라 적절한 도구를 선택하여 효율적으로 상태를 관리하고, 유지보수성을 높입니다.


React Hooks

1. useEffect

(1) 최초 실행 시 -> 최초 의존성 배열을 다운받아야 함 -> 상태변수가 되어야함

(2) 의존성 배열이 변경되는 시점

2. useMemo

(1) 메모리제이션

(2) return에서 한 상태변수의 상태변경에 의해 다른 상태변수까지 상태변경되었다고 인지되는 것 방지

(3) 두 개의 인자 : 1) 계산할 값 또는 함수, 2) 의존성 배열

-> 의존성 배열에 포함된 값이 변경될 때만 게산이 다시 수행

3. useRef

(1) 디자인 변경

(2) DOM 객체에 접근해 스타일 변경

const myRef = useRef<HTMLDivElement>(null);



<div ref={myRef}>박스</div>
 //Ref를 배열로, createRef라는 동적으로 만든 배열 리턴 -> myref를 배열로 만들어주는 메서드
  let myRefs = Array.from({ length: list2.length }).map(() =>
    createRef<HTMLHeadingElement>(),
  );




<div>
{list2.map((user, index) => (
  //useRef 배열 생성 필요 -> createRef
  <h1 ref={myRefs[index]}>{user.name}</h1>
))}
</div>

 

728x90
반응형

'JavaScript > React.js' 카테고리의 다른 글

리액트2 - 스타일  (0) 2024.08.05