반응형

1. LifeCycle

class 기반 react를 오랫동안 써왔다.

그동안은 LifeCycle이 굉장히 중요시 여겨지며

LifeCycle을 기반으로 적재 적소에 함수들을 호출해 개발했다.

 

Hooks로 기반을 변경한 뒤,

useEffect에 의존한 단조로운 LifeCycle위에서 개발하게 되었다.

 

그런데, 이 useEffect에서 호출되는 함수들은

어느 시점에 호출되는걸까?

 

useEffect : render -> useEffect -> (re-rendering)

 

DOM의 레이아웃 배치와 페인팅이 끝난 후,

useEffect의 사이트 이펙트에 해당하는 함수들이 호출된다.

 

여기서 아래와 같은 문제가 발생할 수 있다.

1) 사용자가 짧게나마 빈 페이지를 보게됨

2) 기본 값으로 구성된 페이지를 보게됨

 

대부분의 웹 페이지들이

페이지가 열릴때

데이터를 비동기적으로 불러와

state의 갱신을 동해 화면을 re-rendering해서

사용자에게 제공된다는 것을 생각하면

useEffect를 이런식으로 활용하는것에는

어느정도 문제가 있다고 볼수있겠다.

 

그러면 어떻게 하면 좋을까

하고 알아보니

useLayoutEffect라는 것이 있었다.

 

useLayoutEffect : useLayoutEffect -> render -> (useEffect) -> (re-rendering)

 

useEffect와 달리

DOM이 레이아웃 배치 및 페인팅을 하기 전에

즉, render 보다도 먼저 호출된다.

 

useLayoutEffect를 통해

완벽하게 위의 1), 2) 문제를 제어할수는 없어도

좀더 효과적으로 서비스를 제공할수는 있겠다.

 

(위 문제를 완벽하게 해결하려면 SSR방식의 next를 써야할듯하다.)

 

 

 

2. useState

useState는 단연코 가장 많이 쓰이는 hooks일것이다.

프로젝트를 진행하다보니

코드를 올바르게 작성한듯한데

state가 제때 갱신되지 않아서 의도와 다르게

결과값이 나오는 경우가 심심치않게 보였다.

 

이는 동일블록 내에서 setter를 사용할 때

Closer 구조로 인해 발생하는 문제로,

class기반의 react를 사용할때도 가지고 있던 문제다.

 

class기반에서도 

setState(prevState => ({ ...prevState, type: value }));

위와 같이 처리하곤 했었는데

hooks에서도 마찬가지로 위와 같은 방식으로

해당 문제를 해결할 수 있다.

 

예를 들어,

const [list, setList] = useState([]);


const updateList = (data) => {
  // setList(list.concat(data)); <-- X
  
  setList(prevList => {
    const newList = list.concat(data);
    return newList;
  });
}

이런식으로 처리하면 된다.

반응형
반응형

앱 개발이 완료되어가는 시점이다

 

눈이 안좋은 사람들이

시스템 설정상의 폰트 크기를 조정해서

앱의 텍스트나 디자인이 깨지는것을

방지하기위한 체크를 하는 도중

 

(안드로이드에서만)

앱을 백그라운드로 실행해둔 상태에서

환경 설정에서 폰트 크기를 변경한 뒤

다시 앱으로 돌아오니

앱이 튕겨버리는 현상이 나타났다.

 

추적결과

react-native-screens에서

문제가 있는것으로 발견되었다.

 

 rn-screens docs에도 나와 있듯이

// MainAcitivity.java

import android.os.Bundle;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(null); <-- 여기
}

 

이 부분을 수정해줌으로써

튕겨버리는 이슈가 해결되었다.

 

그런데 여기서 파생된 이슈가 있었다.

우리는 기본적으로 폰트에

dp 단위  + font scale 무시를 적용하는데,

 

위의 null 처리로 인해

백그라운드의 앱이 열렸을때

무조건 그 당시의  font-scale을

1로 간주해버리는 것이 아닌가...

 

바꿔 말하자면,

사용자가 시스템 설정에서

폰트 크기를

1 -> 2로 변경한뒤 앱을 열면

앱이 2라는 것을 1이라는 기준으로 잡아버린다.

 

따라서, font scale을 무시하는

우리의 코드는 오작동을 했다.

(우리의 폰트 크기 = dp / font scale)

 

따라서, storage에 항상

이전 폰트 크기를 저장해뒀다가

폰트 크기가 변경된 경우

앱을 재실행 하는 코드를 추가하였다.

(재실행하면 font-scale 기준을 제대로 잡게됨)

 

const detectChangeFontScaleOnAndroid = async () => {
  const fontScale = PixelRatio.getFontScale();
  const _fontScale = await storage.getItem('fontScale');
  storage.setItem('fontScale', fontScale?.toString());
        
  if (_fontScale && _fontScale !== fontScale.toString()) {
    console.log('changed font scale');
    Platform.OS === 'android' && CodePush.restartApp();
  }
}

 

반응형