728x90

아래와 같이, 복사하기 버튼을 눌렀을 때 클립보드에 텍스트를 복사하려면 어떻게 해야할까? 

 

 

Document.execCommand()를 사용하거나 Clipboard API를 활용하는 방법도 있다.  

 

Document.exeCommand()

 

아래는 exeCommand()에 대한 MDN의 설명이다. 

 

When an HTML document has been switched to designMode, its document object exposes an execCommand method to run commands that manipulate the current editable region, such as form inputs or contentEditable elements.

 

즉, HTML document가 디자인 모드로 바뀌면서 exeCommand를 사용하면, form의 input과 같이 편집이 가능한 element를 조작할 수 있다는 것이다. 그래서 element의 내용을 클립보드로 복사할 수 있게 되었다고 이해하면 좋을 것 같다. 

 

따라서, 어떤 element의 innertext를 복사하고자 한다면, 그 element가 editable한 input이나 textarea여야 한다. 

 

만약, 해당 element가 input이나 textarea가 아니라면, 아래의 코드처럼 textarea를 만들었다가 지우는 방식을 사용하면 된다. 

 

    const pinyin = pinyinRef.current.innerText;
    const textField = document.createElement('textarea');
    textField.innerText = pinyin;
    document.body.appendChild(textField);
    textField.select();
    document.execCommand('copy');
    textField.remove();

 

pinyinRef가 내가 복사하려고 하는 text를 가지고 있는 element를 참조하는 ref 객체이다. 

 

그래서 그 pinyinRef.current의 innerText(복사하고자하는 텍스트)를 가져와서 textField라는 임시 textarea의 innerText로 넣어준다. 

 

document에 임시 textarea를 붙여주고, 그 textarea를 select하여 복사하고자 하는 텍스트를 선택하고, 

 

document.execCommand('copy')를 사용하여 해당 텍스트를 클립보드에 복사한다. 

 

그리고 다시, 임시 textarea를 지워주면 된다. 

 

하지만, Document.execCommand()는 MDN 문서에서 알 수 있듯 더 이상 추천하지 않는 방식이다. 

 

대신, clipboardAPI를 사용한다. 

 

 

Clipboard API

 

Clipboard API는 Promise 기반으로 클립 보드 내용을 비동기적으로 접근할 수 있는 API이다. 

 

아주 아주 간단하다. 

 

		const pinyin = pinyinRef.current.innerText;
		navigator.clipboard.writeText(pinyin);

 

navigator.clipboard.writeText 만을 사용해서 가능하다. 즉, 붙여넣고자 하는 text를 인자로 넣어주면 된다. 

 

728x90

'Front-end > React' 카테고리의 다른 글

next에 antd 적용 안 될 때  (0) 2021.04.10
Redux가 필요한 이유와 기본 개념  (0) 2020.11.14
React: props와 state  (0) 2020.10.25
728x90

next에서 antd가 적용이 안 되고 있는 것 같다면, 

모든 페이지에서 공통으로 적용되게 하는 pages 폴더 아래, _app.js 파일에 다음 문장이 import 되어 있는지 확인하자. 

 

import 'antd/dist/antd.css';

 

antd.css를 import해야 antd 적용이 가능하다. 

728x90

'Front-end > React' 카테고리의 다른 글

[React] 클립보드에 텍스트 복사하기  (0) 2021.05.05
Redux가 필요한 이유와 기본 개념  (0) 2020.11.14
React: props와 state  (0) 2020.10.25
728x90

 

Redux란? 

Redux는 JavaScript app을 위한 predictable state container이다. React의 보완재 역할을 하는데, action에 반응하여 상태를 변경하기 때문에 React처럼 UI를 상태에 대한 함수로 기술하는 framework와 잘 어울린다. 

 

React에 Redux가 필요한 이유? 

React로 프로젝트를 진행했을 때, component는 local state를 가지고 application은 global state를 가지게 된다. local state각각의 component가 가지는 state, application은 이 state를 기반으로 만들어진다.  global state는 예를 들어, 유저의 로그인 유무에 따라 application의 state가 달리 보인다고 할 때, application 전체에서 global state는 유지, local state는 global state를 공유하게 되는 것이다. 

local state의 전달이 어려워서 

React로만 프로젝트를 진행하게 될 경우, application이 local state, global state를 관리하기 어렵다. 예를 들어, shopping mall에서 장바구니를 관리하기 위해 최상단 Component인 App.js에서 cart state를 만들고, 각각의 Component에 이를 props로 전달하여 프로젝트를 관리했다고 하자.

 

프로젝트 규모가 작을 때는 단 한 번의 data 이동으로 cart state가 전달된다. 하지만, 프로젝트의 규모가 커지고 Component 수가 늘어난다면 어떨까? 단순히 cart state를 CartItem.js로 전달하고 싶을 뿐인데, 이를 위해 cart props를 사용하지 않는 Component에도 cart props를 전달하게 된다

 

즉, 프로젝트 규모가 커질수록 props로 data를 전달하기 위해 위와 같은 필요 없는 data의 흐름이 생기게 된다. 그리고 만약 CartItem.js로 cart props가 제대로 전달이 되지 않을 경우, 중간에 낀 모든 Component에서 일일이 문제점을 찾아봐야 한다

 

global state의 유지가 어려워서 

Shopping mall을 포함한 대부분의 application에서는 로그인 기능이 구현되어야 한다. 유저의 개인 정보, 결제 정보 등이 있어야 하기 때문이다. 하지만 React만으로 프로젝트를 진행할 경우, global state를 모든 Component에 유지하기가 어렵다. 유저의 인증 정보를 모든 Component에 props로 계속해서 전달해야 하는데, 이때 복잡한 절차를 거쳐야 한다.

 

하지만 Redux를 사용하게 되면 하나의 store를 통해 global state를 포함한 모든 state를 저장하고 유지할 수 있게 되고, 원하는 Component로만 data를 전달할 수 있게 되어 위와 같은 문제가 해결된다.  

 

 

Flux 구조

Flux는 대규모 프로젝트에서 너무 복잡해지는 MVC 구조 단점을 보완하는 단방향 데이터 흐름의 구조이다. Redux는 Flux의 몇 가지 중요한 특성에 영감을 받아 개발되었다. Redux는 Flux 패턴을 좀 더 쉽고 정돈된 형태로 쓸 수 있게 도와주는 라이브러리라고 볼 수 있다.

 

Redux 기본 개념

Actions

Application의 store, 즉 저장소로 data를 보내는 방법. view에서 정의되어있는 action을 호출하면 action creators는 application의 state를 변경해준다.

 

Reducer

Action을 통해 어떠한 행동을 정의했다면, 그 결과 application의 상태가 어떻게 바뀌는지 특정하게 되는 함수. Action의 type에 따라 변화된 state를 반환하게 된다.

 

Store

'무엇이 일어날지'를 나타내는 action, action에 따라 상태를 수정하는 reducer를 저장하는 application에 있는 단 하나의 객체.

 

 

 

 

*잘 정리된 다른 분의 블로그 글을 참고, 요약했습니다. 

medium.com/@jsh901220/react%EC%97%90-redux-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-a8e6efd745c9

 

React에 Redux 적용하기(1)

리덕스(Redux)란?

medium.com

 

 

 

728x90

'Front-end > React' 카테고리의 다른 글

[React] 클립보드에 텍스트 복사하기  (0) 2021.05.05
next에 antd 적용 안 될 때  (0) 2021.04.10
React: props와 state  (0) 2020.10.25
728x90

React component에서 다루는 data는 props와 state, 이 두 가지로 나뉩니다.

 

props는 부모 component가 자식 component에게 주는 값입니다. 자식 component에서는 props를 받아오기만 하고, 받아온 props를 직접 수정할 수 없습니다.

 

반면에 state는 component 내부에서 선언하며, 내부에서 값을 변경할 수 있습니다. 

 

+) props("properties"의 줄임말)와 state는 일반 JavaScript 객체입니다. 두 객체 모두 렌더링 결과물에 영향을 주는 정보를 갖고 있는데, 한 가지 중요한 방식에 차이가 있는 것입니다. props 함수 매개변수처럼 component에 전달이 되는 반면, state 함수 내에 선언된 변수처럼 component 안에서 관리됩니다. 

 

새 Component 만들기 

먼저, src 디렉토리에 MyName이라는 component를 만들어보겠습니다. 

 

import React, { Component } from 'react';

class MyName extends Component {
  render() {
    return (
      <div>
        안녕하세요! 제 이름은 <b>{this.props.name}</b> 입니다.
      </div>
    );
  }
}

export default MyName;

 

자신이 받아온 props 값은 this. 키워드를 통해 조회할 수 있습니다. 지금은 name이라는 props를 보여주도록 설정해두었습니다. 

 

이제 component를 사용해보겠습니다. 

 

import React, { Component } from 'react';
import MyName from './MyName';

class App extends Component {
  render() {
    return (
      <MyName name="리액트" />
    );
  }
}

export default App;

 

import를 통해 component를 불러오고, 렌더링 해보겠습니다. 이렇게 component를 만들고 나면, 일반 태그를 작성하듯이 작성해주면 됩니다. props 값은 name="리액트" 처럼 태그의 속성 설정하듯이 작성해주시면 됩니다. 

 

함수형 Component

위와 같이 단순히 props만 받아와서 보여주는 component의 경우에는 더 간편한 문법으로 작성할 수 있습니다. 바로 함수 형태로 작성하는 것인데요. 위에서 만들었던 MyName component를 다시 작성해보겠습니다. 

 

import React from 'react';

const MyName = ({ name }) => {
  return (
    <div>
      안녕하세요! 제 이름은 {name} 입니다.
    </div>
  );
};

export default MyName;

 

훨씬 간단하게 작성이 가능한 것을 알 수 있는데요! 함수형 component와 클래스형 component의 주요 차이점 state와 LifeCycle이 빠져있다는 점입니다. 그래서 component 초기 마운트가 아주 미세하게 빠르고, 메모리 자원을 덜 사용합니다. 미세한 차이라서 component를 무수히 많이 렌더링 하는 것이 아니라면 성능적으로 큰 차이는 없습니다. 

 

state

state는 동적인 data를 다룰 때 사용합니다. 이번에는 Counter라는 새로운 component를 만들어보겠습니다.

 

import React, { Component } from 'react';

class Counter extends Component {
  state = {
    number: 0
  }

  handleIncrease = () => {
    this.setState({
      number: this.state.number + 1
    });
  }

  handleDecrease = () => {
    this.setState({
      number: this.state.number - 1
    });
  }

  render() {
    return (
      <div>
        <h1>카운터</h1>
        <div>값: {this.state.number}</div>
        <button onClick={this.handleIncrease}>+</button>
        <button onClick={this.handleDecrease}>-</button>
      </div>
    );
  }
}

export default Counter;

 

메소드가 작성된 부분을 자세히 살펴보겠습니다. 

 

handleIncrease = () => {
    this.setState({
      number: this.state.number + 1
    });
  }

  handleDecrease = () => {
    this.setState({
      number: this.state.number - 1
    });
  }

 

component에 메소드를 작성해주었는데, 메소드는 아래의 형식으로도 작성할 수 있습니다. 

 

handleIncrease() {
    this.setState({
      number: this.state.number + 1
    });
  }

  handleDecrease() {
    this.setState({
      number: this.state.number - 1
    });
  }

 

이렇게 하면 나중에 버튼에서 클릭 이벤트가 발생했을 때, this가 undefined로 나타나서 제대로 처리되지 않게 됩니다. 함수가 버튼의 클릭 이벤트로 전달되는 과정에서 'this'와의 연결이 끊겨버리기 때문인데요. 이를 고쳐주려면 constructor에서 아래처럼 해주면 됩니다. 

 

constructor(props) {
    super(props);
    this.handleIncrease = this.handleIncrease.bind(this);
    this.handleDecrease = this.handleDecrease.bind(this);
  }

 

이렇게 이중으로 작성하는 것보다는, 제일 위에 작성된 코드처럼 아예 화살표 함수 형태로 작성하면, this가 풀리는 것에 대해 걱정하실 필요가 없습니다. 

 

이제 각 메소드에 들어있는 this.setState에 대해 알아봅시다. state에 있는 값을 바꾸기 위해서는 this.setState를 무조건 거쳐야 합니다. React에서는 이 함수가 호출되면 component가 re-rendering 되도록 설계되어 있습니다. 

 

setState는 객체로 전달되는 값만 업데이트 해줍니다. 

 

아래의 코드를 보면,  state에 number와 foo라는 값이 있습니다. 

 

state = {
    number: 0,
    foo: 'bar'
  }

 

this.setState({ number: 1 }); 을 하게 되면 foo는 그대로 남고, number 값만 업데이트됩니다.

 

setState는 객체의 깊숙한 곳까지 확인하지 못합니다. 예를 들어 state가 아래와 같이 설정되어 있다고 해봅시다. 

 

state = {
    number: 0,
    foo: {
      bar: 0,
      foobar: 1
    }
  }

 

아래와 같이 한다고 해서 foobar 값이 업데이트 되지 않습니다. 

 

this.setState({
  foo: {
    foobar: 2
  }
})

 

그냥 기존의 foo 객체가 아래와 같이 바뀌어버립니다.

 

{
  number: 0,
  foo: {
    foobar: 2
  }
}

 

대신 위와 같은 상황에서는 아래와 같이 해주어야 합니다. 

 

this.setState({
  number: 0,
  foo: {
    ...this.state.foo,
    foobar: 2
  }
});

 

...은 JavaScript의 전개 연산자입니다. 기존의 객체 안에 있는 내용을 해당 위치에 풀어준다는 의미입니다. 

setState에 객체 대신 함수 전달하기 

setState를 사용하여 값을 업데이트할 때(기존의 값을 참고하여 업데이트할 때) 조금 더 나은 문법으로 할 수가 있는데요. 

 

기존에 작성했던 코드는 아래와 같죠? 

 

this.setState({
  number: this.state.number + 1
});

 

큰 문제는 아니지만 굳이 또 this.state를 조회해야 하는데요. 아래와 같이 조금 더 나은 문법으로 작성할 수 있습니다. 

 

this.setState(
  (state) => ({
    number: state.number
  })
);

 

여기서 조금 더 나아가면 아래와 같이 작성할 수도 있습니다. 

 

this.setState(
  ({ number }) => ({
    number: number + 1
  })
);

 

(state)가 ({ number })가 되었는데, 이건 비구조화 할당이라는 문법입니다. 이 문법은 아래처럼 사용할 수 있는데요. 

 

const { number } = this.state;

 

결국 코드를 조금 덜 작성하고 싶다면 아래처럼 하면 된답니다. 

 

const { number } = this.state;
this.setState({
  number: number + 1
})

 

 

자료 출처

- velopert.com/3629

 

누구든지 하는 리액트 4편: props 와 state | VELOPERT.LOG

이 튜토리얼은 10편으로 이뤄진 시리즈입니다. 이전 / 다음 편을 확인하시려면 목차를 확인하세요. 리액트 컴포넌트에서 다루는 데이터는 두개로 나뉩니다. 바로 props 와 state 인데요, 미리 요약

velopert.com

- ko.reactjs.org/docs/faq-state.html

 

컴포넌트 State – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

728x90

'Front-end > React' 카테고리의 다른 글

[React] 클립보드에 텍스트 복사하기  (0) 2021.05.05
next에 antd 적용 안 될 때  (0) 2021.04.10
Redux가 필요한 이유와 기본 개념  (0) 2020.11.14

+ Recent posts