728x90
반응형

VScode로 코딩을 치고있는데, 자꾸 jsx return 컴포넌트 들에 붉은 에러 줄이 표시됐다.

물론 컴파일엔 문제가 없어서 vsCode문제겠거니 하고있었는데, 

그냥 눈이 편하게 하기위해 붉은 에러줄을 없애기로 했다.

 

tsconfig.json 에 가보니

 

{
"extends": "@tsconfig/react-native/tsconfig.json",
}

덩그러니 한줄만 있었고, 붉은 줄이 표시되고있었다.

 

해당 key-value의 에러 메세지는 file '@tsconfig/react-native/tsconfig.json' not found.

 

이었고,

"jsx": "react-jsx"

를 밑에 추가해주니, 

 

'jsx' should be set inside the compilerOptions 라는 붉은 줄이 나왔다.

tsconfig.json을 

{
"extends": "@tsconfig/react-native/tsconfig.json",
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"jsx": "react"
}
}

로 수정해주고

 

VScode를 재시작하니 해결

 

728x90
반응형
728x90
반응형

지금까지 RN 프로젝트를 해오면서, 짧은 개발기간을 핑계로 많은 상태관리 라이브러리가 있으면서

익숙하던 redux를 항상 고집해왔다.

zustand와 mobx도 실무에서 많이 사용하는 걸로 알고있는데

항상 무엇인가 가벼운(?) 프로젝트에서 많이 사용한다는 잘못된 선입견이 생겨서인지

신규 프로젝트를 구상할때 항상 redux / asyncstorage / persist-store 들로 상태관리를 했다.

 

성장하지 않는 느낌이 들어서, 이번에 짧은 개발기간임에도 불구하고, 이꽉물고 새로운 상태관리를 적용해보려했다.

결과적으로 말하자면 redux를 사용할때보다 보일러 플레이트가 현저히 줄어서, 코드 치기가 쉬웠다.

 

이번 글에선 react-native cli로 생성한 프로젝트에 mobx 를 적용하는 간단한 설명을 메모해 두려고한다.

항상 새로운 라이브러리를 쓴다는건 신나는 일이고, 결국엔 거의 비슷한 로직으로 돌아간다는게 참 재밌는거 같다.

 

당연히 mobx도, redux처럼 여러개의 store를 사용할수있고(redux에서 여러개의 reducer를 root reducer로 합치는 것과 동일)

하나의 store에 여러값을 저장 할 수 있다.

 

yarn add mobx                                                                             
yarn add mobx-react

 

일단 mobx 와 mobx-react 를 프로젝트에 import 해준다

( mobx-react-lite를 임포트 해주라는 글들도 있지만, mobx-react-lite 내가 적용할때는 babel쪽 syntax에러가 많이 발생해서

mobx-lite를 import해 줬다.)

 

기본 구조

hooks/useRootData.js 는 mobx를 쓰는 hook으로

 

소스코드는

import {useObserver} from 'mobx-react';
import React, {useContext} from 'react';
import {storesContext} from '../utils/context';

export const useStoreData = (context, storeSelector, dataSelector) => {
const value = useContext(context);
if (!value) {
throw new Error('No store');
}
const store = storeSelector(value);

return useObserver(() => {
return dataSelector(store);
});
};

export default dataSelector => {
return useStoreData(storesContext, contextData => contextData, dataSelector);
};

 

import {observable, runInAction} from 'mobx';

const createStore = () => {
const anotherStore = {
anotherKey: observable.box('anotherKey'),
changeAnotherKey: data =>
runInAction(() => anotherStore.anotherKey.set(data)),
};

return anotherStore;
};

const anotherStore = createStore();
export default anotherStore;

 

import {observable, runInAction} from 'mobx';

const createStore = () => {
const loginInfoStore = {
loginInfo: observable.box('userName'),
changeLoginInfo: data =>
runInAction(() => loginInfoStore.loginInfo.set(data)),
connect: observable.box(true),
changeConnect: data => runInAction(() => loginInfoStore.connect.set(data)),
};

return loginInfoStore;
};

const store = createStore();
export default store;

 

import loginInfoStore from './loginInfoStore';
import anotherStore from './anotherStore';

const createRootStore = () => {
return {
loginInfoStore,
anotherStore,
};
};

export default createRootStore;
import {useLocalObservable} from 'mobx-react';
import React, {createContext} from 'react';

import createRootStore from '../store/index';

export const storesContext = createContext(null);

export const StoreProvider = ({children}) => {
const store = useLocalObservable(createRootStore);

return (
<storesContext.Provider value={store}>{children}</storesContext.Provider>
);
};

이 소스코드들을 두가지 store에 한스토어당 2가지이상을 세팅하는 예제로 사용하면 된다.

 

상태값을 사용하고 싶은 component에서

 

const {loginInfo, changeLoginInfo, connect, changeConnect, anotherKey} =
useStoreData(({loginInfoStore, anotherStore}) => ({
loginInfo: loginInfoStore.loginInfo.get(),
changeLoginInfo: loginInfoStore.changeLoginInfo,
connect: loginInfoStore.connect.get(),
changeConnect: loginInfoStore.changeConnect,
anotherKey: anotherStore.anotherKey.get(),
}));

해당 hook으로 state, setState 값을 선언해주고

 

changeConnect(!connect);

이런식으로 사용해주면된다.

 

이번 프로젝트에 mobx의 기본 구조를 적용하면서, 내가 redux-saga / redux-thunk 등의 미들웨어가 mobx에서 어떻게 적용되는지,

mobx의 persist-store적용은 어떻게 하는지 등에 대해 궁금증이 생겼다. 

 

개발은 참 재미있다.

728x90
반응형
728x90
반응형

현재 우리 회사에서 서비스 하고있는 플랫폼엔 모두 Oauth가 적용되어있다.

 

최근 런칭한 서비스를 QA 돌리는중에, 로그아웃하니 처음 연결했던 구글 아이디로만 로그인한다는 QA가 있어서

 

아차 싶었다.

 

항상 Oauth를 사용해서 로그인 할때는, 해당 Oauth sdk(위젯)에서 로그아웃을 실행해줘야한다.

 

룰루랄라 해당 기능에서 로그인 기능을 만들어 놓은 함수

 

public void googleOauthSignOut() {
    try {
    mGoogleSignInClient.signOut()
            .addOnCompleteListener(this, task -> {
                mAuth.signOut();
            });
    gsa = null;
    }catch (Exception e){
        Log.e("signOut error :::;",e.toString());
    }
}

를 import 해서 사용했더니

 

Attempt to invoke virtual method 'android.os.Looper android.content.Context.getMainLooper()' on a null object reference

 

해당 에러가 났다.

 

전역으로 context를 관리하는데도, 가끔 nullpointException이 발생한다.

 

찾아보니 onCreate에서 객체 선언을 해줘야 한다는 글이 있어서, 해당 기능을 사용하는 Activity onCreate에서 

 

GoogleSignInOptions googleSignInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(getString(R.string.default_web_client_id))
        .requestEmail()
        .build();

mGoogleSignInClient = GoogleSignIn.getClient(this, googleSignInOptions);

객체 선언을 해줬더니 정상 작동했다.

 

참고로 로그아웃할때는 항상

 

instance초기화(fcm / oAuth / local db 등등)을 잊지 말아야하는데, 이번 QA 검수 넣은 apk엔 oAuth 관련 초기화가 빠져있었다.

728x90
반응형
728x90
반응형

테스트 폰을 새로 받아서 기존 프로젝트를 빌드해보는데

 

The application could not be installed: SHELL UNRESPONSIVE

라는 에러가 떴다.

 

adb devices 명령어를 쳐봐도 제대로 연결이 되어있다고 나오는데, 

 

cache를 제거하고 새로 시작하니 정상작동했다.

 

RN 을 할때는 ./gradlew clean을 밥먹듯이 썼는데, 안드로이드 스튜디오를 사용하면서 캐시나 프로젝트 클린을 자주 사용하지 않는 것같다.

728x90
반응형
728x90
반응형

회사내에서 NFC카드 테그에따라 실행되며 앱안에서 몇가지의 비지니스 로직이 들어가는 샘플앱을 한 일주일만에

만들어 달라는 요청이 있었다.

 

새로나온 버전을 사용해보려고 룰루랄라 오랜만에 신나서 

 

react-native init 프로젝트이름  --template react-native-template-typescript

 

해당 명령어를 입력했는데

 

TypeError: cli.init is not a function

    at run (/usr/local/lib/node_modules/react-native-cli/index.js:302:7)

    at createProject (/usr/local/lib/node_modules/react-native-cli/index.js:249:3)

    at init (/usr/local/lib/node_modules/react-native-cli/index.js:200:5)

    at Object.<anonymous> (/usr/local/lib/node_modules/react-native-cli/index.js:153:7)

해당 에러가 떴다. 

 

오랜만에 리넥의 에러라 설레는 마음으로 찾아보니, react-native-cli 버전이 안맞아서 생기는 문제라고한다.

 

현재 버전을 react-native --version 으로 확인해보니

2.0.1 버전이라고 나왔다.

 

터미널 창에서

 

npm uninstall -g react-native-cli.

yarn global add @react-native-community/cli

react-native init 프로젝트이름 --template react-native-template-typescript

 

명령어들을 순서대로 입력했더니

 

Starting from React Native v0.71 TypeScript is used by default.

 

이런문구와 함께 생성되었다. 0.71버전부터는 typeScript가 디폴트로 적용된다는 기분좋은 안내문구였다.

 

잘실행되다가 

 

Installing Ruby Gems

error /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/universal-darwin21/rbconfig.rb:230: warning: Insecure world writable dir /Users/내이름/Library/Android/sdk/emulator in PATH, mode 040777

Installing Ruby Gems

error Looks like your iOS environment is not properly set. Please go to https://reactnative.dev/docs/environment-setup?os=macos&platform=android and follow the React Native CLI QuickStart guide for macOS and iOS.

 

해당 에러가 떠서

 gem install cocoapods

로 해결하려했지만, permission 에러가 발생해서

chmod go-w /Users/내이름

명령어 실행 후, 

 gem install cocoapods

로 다시 설치해주며 앱실행을 완료했다.

 

두근두근 0.71 버전이 업데이트되고 나서 리넥으로 처음 적용해서 만들어보는데, 씐난다.

 

<FlashList>를 드디어 사용해 볼 수 있겠다

 

728x90
반응형
728x90
반응형

요즘 계속 안드로이드 요구사항을 작업하다가, 오랜만에 react 로 된 웹페이지 요구사항이 들어왔다.

 

소켓 연결에 상태에 따른 버튼 추가 및 재연결 요청사항이었는데

 

오랜만에 리액트 코드를 보게되서 설렜다.

 

기본 원리는 redux 에 socket connected state 값을 하나 추가해주고, dispatch 를 통해 값을 바꿔주는 식으로 적용했다.

 

useDispatch  훅을 분리된 소켓 모듈에서 바로 import 해줘서 쓰지 못하기때문에,

 

App.tsx 에서

export const socektConnectedRef = React.createRef();

선언 후, App.tsx에서 ref값을 하나

socektConnectedRef.current =(connected)=>{ dispatch(setSocketConnected({ socketConnected: connected}));}

함수를 선언해주고

 

해당 소켓 모듈에서 

function error_handler(err) {
insert_system_message('error', 'socket.io error : ' + err.toString());
console.log('fnChat.js > socket.io error > err = ', err);
try {
socektConnectedRef?.current(false);
} catch (error) {
console.log("socektConnectedRef error :::",error);
}
}

이런식으로 사용해주었다.

 

리넥으로 앱을 할때는 ref값을 많이 사용하지 않도록 지양했고, 전역으로 쓰는 ref값을 맥시멈 4~5개로 제한했었는데, 

 

지금 웹뷰에 붙어있는 웹에선 전역 ref값을 하나만 사용중이라 이런식으로 처리했다.

 

당연히 소켓 연결상태에 따른 뷰변화는

 

const socketConnected = useSelector((state) => state.langData.socketConnected);

을 통해 적용했다.

 

안드로이드를 하면서 많이 느끼는거지만, js 가 좋다.

728x90
반응형
728x90
반응형

1. React에서 클래스형 컴포넌트를 지양하는 이유

React에서 클래스형 컴포넌트를 사용하지 않는 이유는 다음과 같습니다:

  1. 복잡한 문법과 생명주기 관리: 클래스형 컴포넌트는 상속 구조를 사용하고, 복잡한 생명주기 메서드를 포함합니다. 이로 인해 컴포넌트의 이해와 유지보수가 어려울 수 있습니다.
  2. 코드의 가독성과 간결성: 클래스형 컴포넌트는 constructor, render 메서드 등의 추가적인 문법을 요구하며, this 키워드를 사용해야 합니다. 이는 코드의 가독성과 간결성을 저하시킬 수 있습니다.
  3. 성능 이슈: 클래스형 컴포넌트는 더 많은 메모리를 사용하고, 인스턴스를 생성할 때 추가적인 비용이 발생합니다. 또한, 클래스형 컴포넌트는 바인딩과 메서드 호출에 대한 오버헤드가 있을 수 있습니다.
  4. 함수형 컴포넌트와 훅의 도입: React 16.8 버전 이후부터 함수형 컴포넌트와 훅(Hook)이 도입되었습니다. 함수형 컴포넌트는 클래스형 컴포넌트와 비교하여 간단하고 명확한 문법을 가지며, 훅을 통해 상태 관리와 생명주기 기능을 활용할 수 있습니다. 이로 인해 개발자들은 함수형 컴포넌트와 훅을 선호하게 되었습니다.
  5. 더 나은 추상화와 컴포넌트 재사용성: 함수형 컴포넌트는 순수 함수처럼 동작하고, 렌더링 결과를 반환하는 형태로 작성됩니다. 이로 인해 함수형 컴포넌트는 더 나은 추상화를 제공하며, 컴포넌트의 재사용성을 높일 수 있습니다.

따라서, React에서는 클래스형 컴포넌트보다 함수형 컴포넌트와 훅을 주로 사용하고, 함수형 프로그래밍의 개념과 원칙에 따라 개발하는 것을 권장합니다.

 

2.Redux toolkit이란

Redux Toolkit은 Redux를 사용할 때 개발자들에게 편의성을 제공하고 생산성을 향상시키기 위한 공식적인 도구 세트입니다. Redux Toolkit은 Redux의 핵심 기능을 간소화하고 보일러플레이트 코드를 최소화하여 개발자들이 더 간편하게 상태 관리를 할 수 있도록 도와줍니다.

Redux Toolkit이 제공하는 기능과 도구는 다음과 같습니다:

  1. configureStore(): Redux store를 설정하는 함수입니다. Redux Toolkit에서 제공하는 configureStore 함수를 사용하면 Redux store를 초기화하고 필요한 미들웨어와 Redux DevTools를 설정할 수 있습니다.
  2. createAction(): 액션을 생성하는 함수입니다. createAction 함수를 사용하면 액션 생성자 함수를 직접 작성할 필요 없이 간단하게 액션을 생성할 수 있습니다.
  3. createReducer(): 리듀서를 생성하는 함수입니다. createReducer 함수를 사용하면 보일러플레이트 코드 없이 간단하게 리듀서를 작성할 수 있습니다. createReducer 함수는 immer 라이브러리를 내부적으로 사용하여 불변성을 유지하면서 상태를 업데이트할 수 있습니다.
  4. createSlice(): 리듀서와 액션들을 함께 정의하는 함수입니다. createSlice 함수를 사용하면 리듀서와 액션들을 한 곳에서 정의하고 Redux Toolkit이 자동으로 액션 생성자 함수와 리듀서를 생성해줍니다.
  5. createAsyncThunk(): 비동기 작업을 처리하는 액션 생성자 함수를 생성하는 함수입니다. createAsyncThunk 함수를 사용하면 비동기 작업을 처리하는 액션을 간단하게 작성할 수 있습니다. Redux Toolkit은 Promise 기반의 비동기 작업을 처리하기 위해 createAsyncThunk를 제공합니다.
  6. createSelector(): 메모이제이션된 셀렉터 함수를 생성하는 함수입니다. createSelector 함수를 사용하면 상태의 변화가 없는 경우 이전 결과를 재사용하여 성능을 최적화할 수 있습니다.

Redux Toolkit은 Redux를 사용하는 개발자들에게 더욱 편리한 개발 경험을 제공하고, 보일러플레이트 코드를 최소화하여 코드의 가독성과 유지보수성을 향상시킵니다.

 

3.React의 생명주기

 

React 컴포넌트의 생명주기는 컴포넌트가 생성되고 소멸될 때까지의 단계를 의미합니다. React 16.3 버전 이전에는 클래스형 컴포넌트에서 생명주기 메서드를 사용하여 이러한 단계를 제어했지만, 함수형 컴포넌트에서는 React Hook을 사용하여 생명주기와 관련된 작업을 수행합니다. 

React 컴포넌트의 주요 생명주기 메서드는 다음과 같습니다:

1. Mounting (생성 단계)
- constructor(): 컴포넌트가 생성될 때 호출되며, 초기 상태(state)를 설정하고 이벤트 핸들러를 바인딩합니다.
- static getDerivedStateFromProps(): props를 기반으로 state를 설정하거나 업데이트합니다. (React 16.3 이후 추가된 메서드)
- render(): 컴포넌트의 UI를 렌더링합니다.
- componentDidMount(): 컴포넌트가 DOM에 삽입된 후 호출되며, 비동기 작업이나 외부 데이터 로딩과 같은 초기화 작업을 수행합니다.

2. Updating (업데이트 단계)
- static getDerivedStateFromProps(): props를 기반으로 state를 업데이트합니다.
- shouldComponentUpdate(): 컴포넌트의 업데이트 여부를 결정합니다. 성능 최적화를 위해 사용될 수 있습니다.
- render(): 컴포넌트의 UI를 업데이트하여 다시 렌더링합니다.
- componentDidUpdate(): 컴포넌트의 업데이트가 DOM에 반영된 후 호출되며, 비동기 작업이나 상태 변경에 따른 추가 작업을 수행합니다.

3. Unmounting (소멸 단계)
- componentWillUnmount(): 컴포넌트가 DOM에서 제거되기 전에 호출되며, 이벤트 핸들러 해제, 타이머 정리 등의 클린업 작업을 수행합니다.

React Hook을 사용하는 함수형 컴포넌트에서는 useEffect Hook을 통해 생명주기와 관련된 작업을 수행합니다. useEffect는 컴포넌트가 생성, 업데이트, 소멸될 때 특정 작업을 수행할 수 있도록 도와줍니다. useEffect를 사용하여 componentDidMount, componentDidUpdate, componentWillUnmount와 같은 동작을 대체할 수 있습니다.

React 17 버전 이후에는 더 세부적인 생명주기 단계로 분리된 리액트 생명주기를 사용할 수 있는 Concurrent Mode와 함께 useTransition Hook도 도입되었습니다. 이를 통해 렌더링 우선

 순위를 조절하고 부드러운 사용자 경험을 제공할 수 있습니다.

참고로, 클래스형 컴포넌트와 함수형 컴포넌트의 생명주기는 서로 다르기 때문에, React를 사용할 때에는 해당 버전의 문서와 리액트 훅의 사용법을 참조하여 정확한 생명주기를 이해하고 활용하는 것이 중요합니다.

 

4.Mobx

MobX는 JavaScript 상태 관리 라이브러리로, React와 함께 사용되는 경우 많이 애용됩니다. MobX는 간단하고 직관적인 API를 제공하여 복잡한 상태 관리를 간소화하고, 애플리케이션의 반응성과 성능을 향상시키는 데 도움을 줍니다.

MobX의 주요 특징은 다음과 같습니다:

  1. Observable 상태: MobX는 상태를 Observable 객체로 변환하여 관찰 가능하게 만듭니다. 이러한 Observable 상태는 애플리케이션에서 변화가 발생할 때 자동으로 추적되고 업데이트됩니다.
  2. 자동적인 리액트: MobX는 자동으로 상태 변경을 감지하고, 변경된 상태에 따라 관련된 컴포넌트를 자동으로 업데이트합니다. 이는 React 컴포넌트를 작성할 때 명시적인 업데이트 로직을 작성하지 않아도 되는 장점을 제공합니다.
  3. 간단한 문법: MobX는 단순하고 직관적인 문법을 제공하여 상태 관리를 쉽게 할 수 있습니다. 상태 변경에 대한 액션을 작성하고, 이를 실행하여 상태를 변경할 수 있습니다.
  4. 컴퓨티드 값: MobX는 컴퓨티드 값(Computed Value)를 제공하여 상태에 기반한 파생된 값들을 효율적으로 계산하고 캐싱할 수 있습니다. 이는 성능 개선과 코드 가독성을 향상시키는 데 도움을 줍니다.
  5. 액션과 리액션: MobX는 액션(Action)과 리액션(Reaction)의 개념을 제공하여 상태 변경을 관리하고, 관련된 작업을 수행할 수 있습니다. 액션은 상태를 변경하는 함수를 의미하며, 리액션은 상태 변경에 대한 반응으로 추가 작업을 수행하는 함수를 의미합니다.

MobX는 React 외에도 Angular, Vue 등 다양한 프레임워크와 함께 사용할 수 있으며, React와 함께 사용하는 경우 MobX React와의 통합을 통해 더욱 효율적인 상태 관리를 구현할 수 있습니다.

 

5.상태관리 라이브러리

React 애플리케이션에서 사용할 수 있는 주요 상태 관리 라이브러리는 다음과 같습니다:

  1. React Context: React에 기본적으로 내장된 상태 관리 기능입니다. Context를 사용하면 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 수 있습니다. 하지만 복잡한 상태 관리나 전역 상태 관리에는 다소 제한적일 수 있습니다.
  2. Redux: 가장 인기 있는 상태 관리 라이브러리로, 전역 상태를 관리하는데 사용됩니다. Redux는 단방향 데이터 흐름을 따르며, 상태 변경을 예측 가능한 방식으로 관리합니다. Redux는 액션(Action), 리듀서(Reducer), 스토어(Store) 등의 개념을 사용하여 상태를 업데이트하고, 컴포넌트 간에 상태를 공유합니다. Redux Toolkit과 함께 사용하면 보일러플레이트 코드를 최소화하고 개발 생산성을 향상시킬 수 있습니다.
  3. MobX: 간단하고 직관적인 API를 제공하는 상태 관리 라이브러리로, React와 함께 사용될 때 주로 선택되는 라이브러리입니다. MobX는 Observable 상태를 사용하여 상태의 변화를 감지하고, 관련된 컴포넌트를 자동으로 업데이트합니다. MobX는 리액트 컴포넌트를 작성할 때 상태 변경에 대한 명시적인 업데이트 로직을 작성하지 않아도 되는 장점을 가지고 있습니다.
  4. Zustand: 간단하고 가벼운 상태 관리 라이브러리로, Hook 기반으로 동작합니다. Zustand는 React의 내장 상태 Hook(useState)과 유사한 API를 제공하며, 전역 상태를 관리하는데 사용됩니다. Zustand는 Redux와 MobX에 비해 보일러플레이트 코드가 적으며, 간단한 상태 관리에 적합한 선택지입니다.
  5. Recoil: 페이스북에서 개발한 상태 관리 라이브러리로, React 애플리케이션에서 전역 상태를 효율적으로 관리하기 위해 사용됩니다. Recoil은 React의 특징인 컴포넌트 계층 구조를 활용하여 상태를 관리하며, 선택적인 지연 로딩과 코드 스플리팅을 지원합니다.

이 외에도 MobX-State-Tree, Effector, Valtio 등의 다양한 상태 관리 라이브러리가 있으며, 선택할 때 프로젝트의 규모, 복잡성, 개발자 선호도 등을 고려해야 합니다. 각 라이브러리는 고유한 특징과 사용 방법을 가지고 있으므로, 문서와 예제를 참고하여 적합한 상태 관리 라이브러리를 선택할 수 있습니다.

 

6.보일러플레이트 코드

보일러플레이트 코드(Boilerplate code)는 어떤 작업을 수행하기 위해 반복적으로 작성되는 일반적이고 표준화된 코드를 말합니다. 이는 특정한 작업이나 패턴을 구현하기 위해 항상 필요한 기본 코드 또는 템플릿으로 생각할 수 있습니다.

보일러플레이트 코드는 주로 프레임워크나 라이브러리의 초기 설정, 구조, 표준 코드 패턴 등을 포함합니다. 예를 들어, React에서 새로운 컴포넌트를 만들 때, 초기 상태 설정, 라이프사이클 메서드의 구현, 이벤트 핸들러의 바인딩 등은 보일러플레이트 코드의 일부입니다.

보일러플레이트 코드는 개발자가 반복적이고 일상적인 작업에 시간을 소비하지 않고 더 쉽게 시작할 수 있도록 도와줍니다. 또한 팀 간의 일관된 코드 작성을 장려하고, 프로젝트의 구조와 표준을 정의하는 데 도움이 됩니다.

보일러플레이트 코드는 일반적으로 템플릿, 스캐폴딩 도구, 코드 생성기 등을 통해 자동으로 생성하거나, 프레임워크와 라이브러리의 문서와 예제에서 참고하여 수동으로 작성할 수 있습니다.

728x90
반응형
728x90
반응형

WebViewClient를 extends 한 webview 클래스를 만들어서 공통으로 사용중이다.

 

private class CustomWebViewClient extends WebViewClient {


    @Override
    public void onPageStarted(android.webkit.WebView webview, String url, Bitmap favicon) {
        webview.setVisibility(webview.INVISIBLE);
    }

    @Override
    public void onPageFinished(android.webkit.WebView view, String url) {

        spinner.setVisibility(View.GONE);
        view.setVisibility(web.VISIBLE);
        super.onPageFinished(view, url);

    }

    @Override
    public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
        Log.e("doUpdateVisitedHistory url:::::",url);
        Log.e("doUpdateVisitedHistory view.toString:::::",view.toString());
        currentUrl = url;
        super.doUpdateVisitedHistory(view, url, isReload);
    }
}

위의 소스 코드중에 doUpdateVisitedHistory 를 통해, 웹의 url등을 알 수 있다.

728x90
반응형
728x90
반응형

react native 로 aa를 할때, 모든 개발이 그렇듯, 공통 모듈을 분리해놓는 것이 좋다.

 

rn은 크로스플랫폼 개발이라서, ios 노치 디자인 등 신경써야 할 것들이 많다.

 

대부분의 개발자분들이 그렇듯, app.tsx app.js에 앱 전반에 영향을 미치는 부분들을 생각해서 기본구조를 짤것이다.

 

예시를 들어보면

 

<BackgroundTask>
<ReRenderProvider>
<ThemeProvider>
<LanguageProvider>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<NavigationContainer ref={navigationRef}>
<Stack.Navigator

등으로 app.tx app.js를 구성하는 경우가 있었다.

 

앱의 foreground / background 상태를 체크하기 위한 BackgroundTask

강제 랜더링을 위한 ReRenderProvider

앱의 테마를 위한 ThemeProvider

언어 다국어 처리를 위한 LanguageProvider

local 저장소인 store를 위한 ProviderPersistGate

그 안에 네비게이션 컨테이너를 넣어준다.

 

기획과 스토리 보드에 따라

SafeAreaProvider

ErrorBoundary

도 적용하는 것이 좋다.

 

앱에서 주로쓰는 firebase noti 들과, 코드푸쉬는 주로 index.js에서 사용했다.

728x90
반응형
728x90
반응형

에러 내용을 읽어보면 31 버전부터는 pendingIntent에 mutable 인지 immutable 인지 명시가 되어 있어야 한다고한다.

 

기존 코드에 FLAG_IMMUTABLE을 추가해줬다.

기존코드

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT );

추가후 코드

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

 

728x90
반응형

+ Recent posts