[3] React.js 주요 개념 이해하기

Doozuu·2023년 4월 10일
0

React

목록 보기
15/23
post-custom-banner

📌 이벤트 사용하기

⭐️ react에서는 html과 달리 이벤트에 camelCase를 사용한다.

html에서는 onclick 이라고 나타냈지만 react에서는 onClick 이라고 쓴다.

1. onClick

onClick 이벤트는 특정 element가 클릭됐을 때 정의된 함수를 호출하는 방식으로 사용한다.

2. onChange

onChange 이벤트는 특정 element에 변화가 생겼을 때 정의된 함수를 호출하는 방식으로 사용한다.

3. mouse 이벤트

  • onMouseMove 이벤트는 특정 tag 영역 안에서 마우스 커서가 움직일 때 발생한다.
  • onMouseOver 이벤트는 특정 tag 영역 안에 마우스 커서가 진입할 때 발생한다.
  • onMouseOut 이벤트는 특정 tag 영역 안에 마우스 커서가 진입했다가 벗어날 때 발생한다.

4. key 이벤트

  • onKeyDown 이벤트는 키를 눌렀을 때 동작한다.
    - 키를 누르고 떼는 동작 자체에 반응한다.
  • onKeyPress 이벤트는 키를 눌렀을 때 동작한다.
    - 문자가 실제로 입력됐을 때 반응한다.
  • onKeyUp 이벤트는 눌려 있던 키에서 손을 뗐을 때 동작한다.
    - 키를 누르고 떼는 동작 자체에 반응한다.

5. onSubmit

onSubmit 이벤트는 <form> 태그에 사용한다. <input> 태그를 클릭하거나 enter를 누르면 발생한다.



📌 Ref 사용하기

Ref는 컴포넌트 내부의 요소에 접근할 때 사용된다. Ref를 사용하면 DOM 요소를 직접 조작하거나, 컴포넌트 인스턴스에 접근할 수 있다.

useRef

useRef는 React에서 Ref 객체를 생성하는 Hook이다.
useRef를 사용하면 클래스 컴포넌트의 this.refs와 같은 기능을 함수형 컴포넌트에서 사용할 수 있다.

const myRef = useRef(initialValue);
import React, { useRef } from 'react'; // import 하기

function MyComponent() {
  const inputRef = useRef(null); // input 참조

  const handleClick = () => {
    inputRef.current.focus(); // 버튼 클릭시 focus 효과
  }

  return (
    <div>
      <input type="text" ref={inputRef} /> // 참조할 요소
      <button onClick={handleClick}>포커스</button>
    </div>
  );
}



📌 커링 함수 구현하기

커링(Currying) 함수는 함수를 반환하는 함수로, 여러 개의 인수를 받는 함수를 하나의 인수만 받는 함수들의 중첩 함수로 나누는 것이다.
이를 통해 함수의 재사용성을 높일 수 있다.

function multiply(x) {
  return function(y) {
    return x * y;
  }
}

// 위 함수를 ES6 화살표 함수로 간단히 표현하면 다음과 같다.
const multiply = x => y => x * y;

const double = multiply(2); // (y) => 2 * y
const triple = multiply(3); // (y) => 3 * y

console.log(double(4)); // 8
console.log(triple(4)); // 12



📌 고차 컴포넌트 구현하기

커링과 같이 함수 자체를 인자로 받거나 반환하는 함수를 고차 함수라고 한다.
이와 비슷하게 컴포넌트를 인자로 받거나 반환하는 함수를 고차 컴포넌트라고 한다.

  1. MyComponentWithLoadingIndicatorwithLoadingIndicator함수를 실행시킨다.
  2. withLoadingIndicator함수는 props에서 isLodaing과 나머지 데이터를 분리해 isLoading이 true일 때 로딩 문구를 return하고, 그 외에는 Component에 나머지 데이터를 전달한다.
  3. Component는 나머지 데이터를 props로 받아서 데이터의 title과 content를 보여준다.
import React from 'react';

function withLoadingIndicator(Component) {
  return function WithLoadingIndicator(props) {
    const { isLoading, ...rest } = props;

    if (isLoading) {
      return <div>Loading...</div>;
    }

    return <Component {...rest} />;
  }
}

function MyComponent(props) {
  const { data } = props;

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
}

const MyComponentWithLoadingIndicator = withLoadingIndicator(MyComponent);

function App() {
  const isLoading = true;
  const data = { title: 'Hello', content: 'World!' };

  return (
    <MyComponentWithLoadingIndicator isLoading={isLoading} data={data} />
  );
}



📌 Context api 사용하기

props를 사용하면 데이터를 부모 컴포넌트에서 자식 컴포넌트로 전송할 수 있다.

그런데 만약 손자 컴포넌트가 부모 컴포넌트의 데이터를 필요로 한다면, 자식 컴포넌트가 중간에서 데이터를 전달해야 한다.(부모 -> 자식 -> 손자로 전달)

이때 자식 컴포넌트가 부모 컴포넌트의 데이터가 필요하지 않은 상황이라면 불필요한 코드를 작성하게 된다.(관계가 깊어질수록 전달하기가 매우 번거로워진다.)

컨텍스트는 데이터의 공급자와 소비자를 정의하고 데이터가 필요한 컴포넌트만 사용할 수 있게 구현할 수 있다.

useContext

일반적으로 컨텍스트는 여러 컴포넌트에서 공유해야 하는 데이터를 저장하고, 이를 자식 컴포넌트에서 사용할 수 있도록 한다. 컨텍스트는 전역으로 사용할 수 있어야 하기 때문에, 보통 최상위 컴포넌트에 위치한다.

예제

ThemeContext.js

import {createContext, useState} from 'react'; // createContext import하기

const themes = {
  light: {
    foreground: '#000000',
    background: '#eeeeee'
  },
  dark: {
    foreground: '#ffffff',
    background: '#222222'
  }
};
// ThemeContext 객체를 만들어 초기값으로 themes.light 전달
export const ThemeContext = createContext(themes.light); 

// ThemeProvider 생성
export const ThemeProvider = ({children}) => {
  const [theme,setTheme] = useState(themes.light);
  
  return(
     <ThemeContext.Provider value={theme}>
    	{children}
    </ThemeContext.Provider>
  )
}
  1. createContext를 이용해 컨텍스트를 만든다.
  2. 컨텍스트의 provider를 만든다.
    • ThemeContext 객체를 사용하려면 ThemeContext.Provider 컴포넌트를 사용해야 한다. ThemeContext.Provider 컴포넌트의 value prop에는 ThemeContext 객체에서 사용할 값을 지정할 수 있다.
    • 또한, 자식 컴포넌트들을 ThemeProvider 컴포넌트로 감싸면 하위 컴포넌트에서 ThemeContext를 사용하여 theme 값을 참조할 수 있다.

ChildComponent.js

import {useContext} from 'react'; // useContext import하기
import {ThemeContext} from '../ThemeContext'; // 사용할 컨텍스트 import 하기

function ChildComponent() {
  const theme = useContext(ThemeContext); // useContext를 이용해 컨텍스트에서 데이터 가져오기

  return (
    <div style={{ color: theme.foreground, backgroundColor: theme.background }}>
      This is a child component
    </div>
  );
}

export default ChildComponent;
  1. 컨텍스트를 사용할 컴포넌트에서 useContext사용할 컨텍스트를 import 해온다.
  2. useContext를 이용해 컨텍스트에서 데이터를 가져와 사용한다.
    • ThemeContext.Provider 컴포넌트를 사용하지 않고, useContext Hook을 사용하면, 초기값이 undefined로 설정되어 에러가 발생할 수 있다.

📌 Context로 부모 데이터 변경하기

props는 데이터가 부모에서 자식 컴포넌트로 단방향으로만 이동할 수 있다. 하지만 컨텍스트를 사용하면 자식 컴포넌트에서 부모 컴포넌트의 데이터를 변경할 수 있다.

-> Provider 컴포넌트에서 상태를 변경하는 함수를 작성하고 이를 value로 전달하면, 자식 컴포넌트에서 전달받은 함수를 이용해 부모 데이터를 변경할 수 있다.

부모 컴포넌트

import { createContext, useState } from 'react';

const MyContext = createContext();

const ParentComponent = () => {
  const [state, setState] = useState({
    name: 'John',
    age: 30,
  });

  const updateState = (name, age) => {
    setState({
      ...state,
      name,
      age
    });
  };

  return (
    <MyContext.Provider value={{ state, updateState }}>
      <ChildComponent />
    </MyContext.Provider>
  );
};

export default ParentComponent;

업데이트 함수의 setState안에 ...state를 쓰는 이유

  • setState 함수를 사용하여 상태를 업데이트할 때, 이전 상태를 완전히 덮어쓰는 대신, 기존 상태의 일부를 변경하고자 할 때 사용된다.
  • ...state는 객체 분해 할당을 사용하여, state 객체의 모든 속성을 현재 상태로 복사하고 새로운 값을 할당하여 변경된 상태를 만든다.
  • 위 코드에서는 기존 state 객체의 모든 속성을 ...state로 복사한 후, name과 age만 새로운 값으로 업데이트하여 새로운 객체를 생성한다.
  • 이렇게 하면 기존 상태를 완전히 덮어쓰지 않고, 일부 속성만 변경할 수 있기 때문에 효율적인 상태 업데이트가 가능하다.

자식 컴포넌트

import { useContext } from 'react';
import MyContext from './MyContext';

const ChildComponent = () => {
  const { state, updateState } = useContext(MyContext);

  const handleClick = () => {
    updateState('Jane', 25); 
    // 컨텍스트로부터 전달받은 update함수를 이용해 부모 데이터 갱신
  };

  return (
    <div>
      <p>{state.name}</p>
      <p>{state.age}</p>
      <button onClick={handleClick}>Update State</button>
    </div>
  );
};

export default ChildComponent;
// 버튼을 클릭하면 'John', 30 에서 'Jane', 25로 바뀐다.



📌 Redux - reducer로 스토어 생성하기

redux는 컨텍스트와 마찬가지로 데이터를 필요한 컴포넌트에서만 요청해 사용할 수 있다.

  • 컨텍스트는 부모 컴포넌트에서 생성한 데이터에 모든 자식 컴포넌트에서 접근할 수 있다.
  • 하지만 redux에서는 컴포넌트 외부의 스토어라는 곳에서 관리한다.
    그래서 컴포넌트 위치에 상관없이 스토어에 접근해 데이터를 사용하고 변경할 수 있다.

redux 설치

npm install --save redux

redux는 데이터를 스토어 > 컴포넌트 > 액션 > 리듀셔 > 다시 스토어의 과정을 통해 변경한다.

index.js

import {createStore} from 'redux'; // 스토어 생성 함수
import reducers from './reducers'; // 데이터 초깃값 설정하고 데이터 변경해주는 함수

const store = createStore(reducers); // store 생성

const listener = () => {
	ReactDOM.render(
    	<App store={store}/>,
        document.getElementById('root')
    );
};

store.subscribe(listener); 
// store를 구독하면 store 데이터에 변화가 있을 때 listener 내부의 render 함수를 실행하고 변경된 데이터를 렌더링한다.
listener(); // 초기 렌더링을 위해 수동으로 render 함수 실행

redux 파트 79 ~ 84는 나중에 추가.



📌 react-cookies save 사용하기

쿠키란 사용자가 접속한 웹 사이트의 서버를 통해 사용자 컴퓨터에 설치되는 정보를 말한다.
쿠키는 사용자 정보를 저장하거나 마케팅을 위한 목적으로 사용될 수 있다.

설치

npm install react-cookies --save

예제

save 함수의 세 가지 파라미터 : 쿠키의 키(userid), 쿠키 값(Doozuu), 쿠키 옵션

import React from "react";
import { Component } from "react";
import cookie from 'react-cookies'; // import

class R085_cookieSave extends Component {
    componentDidMount() {
        const expires = new Date()
        expires.setMinutes(expires.getMinutes() + 60)  // 현재 시간으로부터 60분 후 만료
        cookie.save('userid' , "Doozuu" ,{
            path : '/',   // 쿠키값을 저장하는 서버 경로
            expires,  // 쿠키의 유효시간
            // secure : true // https인 경우에만 쿠키 저장
            // httpOnly : true  // document.cookie로 쿠키 접근하는 것 방지
        });
    }

    render () {
        return (
            <><h3>react-cookies Save</h3></>
        )
    }
}

export default R085_cookieSave;



📌 react-cookies load 사용하기

save 함수가 쿠키를 key-value 쌍으로 저장하는 함수였다면, load 함수는 웹 브라우저에 남아 있는 쿠키에 key로 접근해 value를 가져오는 함수다.

예제

cookie.load(key) : key에 해당하는 value를 가져온다.
쿠키가 저장되기까지 충분한 시간을 두기 위해 setTimout을 사용한다.

import React from "react";
import { Component } from "react";
import cookie from 'react-cookies'; // import

class R085_cookieSave extends Component {
    componentDidMount() {
        const expires = new Date()
        expires.setMinutes(expires.getMinutes() + 60)  // 현재 시간으로부터 60분 후 만료
        cookie.save('userid' , "Doozuu" ,{
            path : '/',   // 쿠키값을 저장하는 서버 경로
            expires,  // 쿠키의 유효시간
            // secure : true // https인 경우에만 쿠키 저장
            // httpOnly : true  // document.cookie로 쿠키 접근하는 것 방지
        });
      setTimeout(function(){
        alert(cookie.load('userid')) // 1초 후 Doozuu 출력
      },1000);
    }

    render () {
        return (
            <><h3>react-cookies Save</h3></>
        )
    }
}

export default R085_cookieSave;



📌 react-cookies remove 사용하기

remove 함수는 웹 브라우저에 남아 있는 쿠키에 key로 접근해 쿠키를 삭제하는 함수다.

예제

import React from "react";
import { Component } from "react";
import cookie from 'react-cookies'; // import

class R085_cookieSave extends Component {
    componentDidMount() {
        const expires = new Date()
        expires.setMinutes(expires.getMinutes() + 60)  // 현재 시간으로부터 60분 후 만료
        cookie.save('userid' , "Doozuu" ,{
            path : '/',   // 쿠키값을 저장하는 서버 경로
            expires,  // 쿠키의 유효시간
            // secure : true // https인 경우에만 쿠키 저장
            // httpOnly : true  // document.cookie로 쿠키 접근하는 것 방지
        });
      setTimeout(function(){
        cookie.remove('userid', { path: '/'}); // 1초 후 useid의 쿠키 값 삭제
      }, 1000); 
      setTimeout(function(){
        alert(cookie.load('userid')) // 1초 후 Doozuu 출력
      },1000);
    }

    render () {
        return (
            <><h3>react-cookies Save</h3></>
        )
    }
}

export default R085_cookieSave;



📌 react-router-dom BrowerRouter 사용하기

라우팅이란, 호출되는 url에 따라 페이지 이동을 설정하는 것이다.
라우팅을 지원하는 패키지로 react-router-dom이 있다.

react-router-dom 패키지는 BrowerRouter, Router, Link의 기능을 제공한다.

  • Router는 호출되는 url에 따라 이동할 component를 정의한다.
  • Link는 a 태그와 같이 페이지에 표시되는 링크를 클릭하면 url을 호출한다.
  • Router와 Link를 사용하기 위해서는 BrowerRouter 태그로 감싸 사용해야 한다.
    (index.js 에서 <App/> 을 BrowerRouter 태그로 감싸준다.)

설치

npm install --save react-router-dom



📌 react-router-dom Route 사용하기

  1. Route를 import한다.
  2. Route 태그에 path 속성으로 호출되는 url 경로, component 속성으로 연결할 컴포넌트를 할당한다.

App.js

import React, {Component} from 'react';
import reactRouter from './reactRouter';
import reactRouter2 from './reactRouter2';
import {Route} from 'react-router-dom'; // import 

class App extends Component{
  	render(){
      return(
        <div className="App">
            <Route exact path='/' component={reactRouter} />
            <Route exact path='/reactRouter2' component={reactRouter2} />
        </div>
		);
    }
}

export default App;



Link는 a 태그와 동일하게 동작한다.

  1. Link를 import 한다.
  2. to 속성으로 이동할 경로를 입력한다.

예시

<Link to={'/reactRouter2'}>reactRouter2</Link>



📌 <react img> 태그 사용하기

react에서는 require 문법을 사용해 이미지 경로를 할당해야 한다.

예시

<img src={require("../img/main/log_img.png") alt=""}/>



📌 lodash 디바운스 사용하기

debounce는 연속된 이벤트 호출이 일어나는 상황에 사용한다.

  • 마지막 이벤트가 실행되고 일정 시간 동안, 추가 이벤트가 발생하지 않을 때 실행되는 함수다.
  • debounce는 꼭 필요한 시점에만 함수를 실행해 서버 자원을 효율적으로 사용할 수 있게 해준다.

설치

npm install --save lodash

예제

  1. 텍스트가 입력될 때마다 debounce 함수를 호출한다.
  2. debounce 함수에 1초의 지연 시간을 할당한다.
  • 실제로 사용자가 입력한 텍스트가 포함된 검색어를 불러와야 할 때, 디바운스를 사용하지 않고 react라는 글자를 입력한다면 r,re,rea,reac,react가 입력되는 시점에 모두 데이터를 호출해야 한다.
  • 그러나 디바운스를 사용하면 react라는 글자가 모두 작성되고 지연 시간 1초가 지난 후 데이터를 한 번만 호출한다.
import React, { Component } from 'react';
import { debounce } from 'lodash'; // import

class reactDebounce extends Component {
	debounceFunc = debounce( () => {
    	console.log("Debounce API Call");
        }, 1000);
    
    render() {
    	return (
        	<>
            	<h2> 검색어 입력 </h2>
                <input type="text" onChange={this.debounceFunc} />
            </>
        )
    }
}

export default reactDebounce;



📌 lodash 스로틀 사용하기

throttle도 debounce와 동일하게 시간 조건을 추가해 실행 횟수를 제한한다.
차이점은 debounce가 연속된 이벤트 중 마지막 이벤트가 발생한 시점부터 특정 시간이 지났을 때 동작한다면, throttle은 발생한 이벤트 수와 관계없이 지정한 시간 단위당 최대 한 번만 동작한다는 것이다.

  • 1초의 실행 시간 간격을 할당한다면, throttle 함수는 1초마다 0개 또는 1개의 로그를 출력한다.

  • 만약 react 라는 검색어를 0초(r), 0.3초(e), 0.5초(a), 1.1초(c), 2초(t)에 입력했다면, throttle은 0초(r), 1초(rea), 2초(react)에 1초 단위로 데이터 호출 코드를 실행한다.

profile
모든게 새롭고 재밌는 프론트엔드 새싹
post-custom-banner

0개의 댓글