반응형

이번 포스팅에서는 React에서 setState의 Callback 함수를 사용하는 경우를 소개합니다.

 


setState의 Callback 함수를 사용하는 경우

react에서 setState의 Callback 함수를 사용하는 경우는 state를 변경 후 변경된 state를 사용하는 경우입니다.

 

우선, Callback 함수를 사용하지 않은 경우 어떠한 문제가 발생하는지 알아봅시다.

 

다음은 [* 2] 버튼을 클릭하면 this.state.num의 값을 2배로 변경 후 콘솔에 this.state.num의 값을 출력하는 함수입니다.

twiceButtonClick = () => {
    this.setState({ num: this.state.num * 2 });
    console.log("state : " + this.state.num);
  };

실행 결과

[* 2] 버튼을 클릭 전 결과입니다.

[* 2] 버튼 클릭 전

[* 2] 버튼을 클릭 후 결과입니다.

[* 2] 버튼 클릭 후

setState 함수가 실행되어 this.state.num의 값이 2로 변경되었는데, 콘솔에는 변경되기 전 값이 출력되었습니다.

 

이러한 이유는 setState가 비동기 함수라서 그렇습니다.

 

setState 함수는 이벤트 핸들러 함수에서 바로 값을 갱신(변경)하는 것이 아니라 이벤트 핸들러 함수가 종료 후 react에 의해 state 값이 갱신됩니다.

 

setState 함수로 state의 값을 변경 후 갱신된 값을 콘솔에 출력하기 위해서는 setState의 Callback 함수를 사용해야 합니다.

 

Class 컴포넌트의 setState Callback

다음 코드는 setState 함수의 정의인데, 2개의 인자가 존재합니다.

setState<K extends keyof S>(
  state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
  callback?: () => void
): void;

첫 번째 인자는 변경할 state를 전달하며, 두 번째 인자는 state가 변경 후 실행되는 callback 함수를 전달합니다. 

 

즉, state의 값을 변경 후 특정한 기능 또는 동작이 실행되도록 하고 싶다면, setState의 두 번째 인자인 callback 함수를 전달하면 됩니다.

 

다음 코드는 this.state.num의 값을 갱신 후 콘솔에 값을 출력하는 코드를 callback 함수로 전달합니다.

twiceButtonClick = () => {
  this.setState(
    { num: this.state.num * 2 }, 
    () => {
      console.log("state : " + this.state.num);
    }
  );
};

실행 결과

[* 2] 버튼을 클릭 전 결과입니다.

[* 2] 버튼 클릭 전

[* 2] 버튼을 클릭 후 결과입니다.

[* 2] 버튼 클릭 후

또 다른 방법으로는 생명주기 함수인 componentDidUpdate를 사용하는 것입니다.

twiceButtonClick = () => {
  this.setState({ num: this.state.num * 2 });
};
  
componentDidUpdate(prevProps, prevState) {
  if (this.state.num !== prevState.num) {
    console.log("state : " + this.state.num);
  }
}

이전 값과 현재 값을 비교해서 값이 일치하지 않으면, 특정 기능 또는 동작이 실행되는 코드를 작성합니다.


Function 컴포넌트의 setState Callback

React 16.8 이후 도입된 Hook은 useState 함수를 사용해서 state를 갱신할 수 있습니다.

 

단, useState 함수는 두 번째 인수가 존재하지 않습니다.

 

대신 useEffect에 선택적 인수로 두 번째 인수인 의존성 배열을 사용합니다.

 

다음은 위에서 작성한 Class 컴포넌트를 Hook으로 변경한 코드입니다.

function App() {
  const [num, setNum] = useState(1);

  function twiceButtonClick() {
    setNum(num * 2);
  }

  function initButtonClick() {
    setNum(1);
  }

  useEffect(() => {
    console.log("num : " + num);
  }, [num]);

  return (
    <div className="App">
      <button onClick={() => { twiceButtonClick(); }} >
        * 2
      </button>
      <button onClick={() => { initButtonClick(); }} >
        Clear
      </button>
      <div>{num}</div>
    </div>
  );
}

 

App 컴포넌트에서 핵심 코드는 useEffect 함수입니다.

useEffect(() => {
  console.log("num : " + num);
}, [num]);

두 번째 인자로 [num]을 전달하여 num이라는 state가 변경되면, useEffect 함수가 실행되도록 합니다.

 

출처: https://developer-talk.tistory.com/229

반응형
반응형

1. 변경한 state value를 화면에 구현하기

reducer / store 개념을 종합하여 버튼을 눌렀을때 값이 변화하는 logic을 구현해본다.

1-1. addEventListener을 활용해서 action dispatch

HTML에서 생성한 버튼 tag(속성)에 click 이벤트를 추가하고,
클릭 시 action dispatch를 발동해서 state + 1 을 하도록 구현한다.

//Vanilla
import { createStore } from "redux"

const add = document.getElementById("add")
const minus = document.getElementById("minus")
const number = document.querySelector("span")

const reducer = (state = 0, action) => {
  if(action.type === "ADD"){
    state = state + 1
  }
  if(action.type === "MINUS"){
    state = state - 1
  }
  console.log(state)
  return state
}
const countStore = createStore(reducer)

const addHandler = () => {
  countStore.dispatch({type:"ADD"})
}

add.addEventListener("click", addHandler)

const minusHandler = () => {
  countStore.dispatch({type:"MINUS"})
}

minus.addEventListener("click", minusHandler)

위 코드에서

add tag(더하기 버튼)에 addEventListener를 통해 클릭하였을때("click"), addHandler 함수를 실행하도록 구성하였다.

이때 addHandler 함수는 action을 dispatch해서, store가 이를 인식하여 reducer를 통한 state value 변화를 일으키도록 유도한다.

위 logic에 대해 log 출력을 살펴보면 state value가 정상적으로 변화함을 확인하였다.

1-2. Subscribe

Reducer가 호출될 때 subscribe되어있는 함수 및 객체를 호출하는 동작 방식

const stateChanged = () => {
  console.log("Reducer Changed!")
}

countStore.subscribe(stateChanged)

위 코드를 실행하게 되면 아래와 같이 Reducer가 호출되면서 subscribe로 정의된 함수도 같이 호출된다.

Store의 subscribe 함수를 이용하게되면 Reducer가 호출되는 시점에서 subscribe를 통해 정의한 함수를 호출 및 동작할 수 있게 된다.

1-3. subscirbe를 활용한 변화한 값 화면에 구현하기

click 이벤트 실행 시 reducer가 호출된다는 원리를 활용해서 subscribe도 같이 동작하도록 구현한다.

const stateChanged = () => {
  number.innerText = countStore.getState()
}

countStore.subscribe(stateChanged)

위 코드와 같이 subscribe를 통해 변화한 상태값을 화면에 구현하도록 HTML tag(속성)과 연결하는 logic을 구현하면, 화면에 해당 값을 그대로 출력할 수 있게 된다.

2. 정리

redux 기본 구조를 간략하게 정리하면 다음과 같다.

  • redux는 React와는 전혀 다르고, 하나의 독립적인 기능을 제공하는 라이브러리이다.
  • redux의 핵심 구조는 store, reducer가 있고 이 둘을 연결하면 reducer 내부의 데이터의 흐름을 일방향화하여 관리를 유용하게 할 수 있다.
  • redux 내부의 데이터는 store에 종속되고, 반드시 redux logic에 의해서만 변화할 수 있다.
  • redux 내부적인 데이터 변화보다는, redux와 action을 연결하여 외부적으로 연결하는 방식을 사용한다.
  • action은 dispatch를 통해 연결할 수 있고, subscribe를 통해 reducer가 호출되는 시점에서 상태값을 얻거나(getState) 화면에 구현하는 함수 등을 구성할 수 있다.
  • dispatch/subscribe/getState 등은 모두 Store가 제공하는 함수들이다.

 

 

출처: https://velog.io/@gyrbs22/Redux-redux-%EA%B8%B0%EB%B3%B8-action-dispatch-subscribe

반응형
반응형

오늘은 갑자기 생긴 오류에 대한 포스팅을 해보려 한다. 업무를 하는 중 갑자기 오류가 나왔다. 내용은 아래와 같다. 콘솔 내용을 확인해보면 버전이 바뀌어서 생긴 오류인거 같다. 

버전이 바뀌면 작고 큰 오류들이 생겨난다. 콘솔 내용을 잘 확인해보면 문제해결을 하는데 있어서 큰 어려움을 겪지 않으며 빠른 해결을 할 수 있다.

콘솔오류

`text-emphasis-variant()` has been deprecated as of v4.4.0. It will be removed entirely in v5.

The `bg-variant` mixin has been deprecated as of v4.4.0. It will be removed entirely in v5.

구글링

구글링을 해서 이것저것 찾던 중 아주 간단한 해결방법을 찾았다. 해당 링크를 보면 "$ignore-warning" 파라미터 값이 추가가 된 것을 확인해볼 수 있다. 

github.com/twbs/bootstrap/blob/v4.4.1/scss/mixins/_text-emphasis.scss#L5

 

twbs/bootstrap

The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web. - twbs/bootstrap

github.com

해결방법

기존 : @include text-emphasis-variant('.text-primary'theme-color('primary'))

수정 :@include text-emphasis-variant('.text-primary'theme-color('primary'), true)



출처: https://felix-escape.tistory.com/409 [행운이 깃든 블로그.]

반응형
반응형

If you are using version > 2.13 then you won't need to install dotenv anymore because it's already built in https://nuxtjs.org/docs/directory-structure/nuxt-config/#runtimeconfig

.env support Similar to vue-cli (*), .env file will be always loaded via dotenv and is accessible via process.env and options._env. process.env is updated so one can use it right inside nuxt.config for runtime config. Values are interpolated and expanded with an improved version of dotenv-expand. .env file is also watched to reload during nuxt dev. Path can be set via cli --dotenv or disabled by --dotenv false.

I created the .env.xxx files and created the corresponding scripts

 

반응형

+ Recent posts