npm 모듈을 사용하다보면 promise 객체를 리턴하지 않아서 콜백으로만 결과를 처리해야 하는 모듈이 있다.

필자는 sqlite3 모듈을 사용중 db.get 함수의 리턴이 promiser가 아니었다.

그래서 해당 모듈의 결과는 콜백으로 받아야 하고 그 결과를 부모 호출자에게 보내기 위해서 Promise로 변환하는 작업이 필요했다.

 

import { Database } from 'sqlite3';
const db = new Database('db.sqlite');

export async function testSqlite(sender: any) {
  db.get('SELECT RANDOM() % 100 as result', (_: any, res: any) => {
    console.log(res);
  });
}

export async function testSqlite2() {
  return new Promise((resolve, reject) => {
    db.get('SELECT RANDOM() % 100 as result', (_: any, res: any) => {
      // if res 가 에러이면 reject(에러)
      //   console.log(res);
      resolve(res);
    });
  });
}

 

설치된 JDK 확인

/usr/libexec/java_home -V

 

java_home 확인

echo $JAVA_HOME

 

JAVA_HOME 수정

vi ~/.zshrc

JS 배열 및 객체에서 일반적인 깊은 복사 얕은 복사 개념에 대해서는 넘어가고, 

nested된 객체 및 배열에 대해 얘기한다.

 

nested는 "중첩된"이라는 뜻인데,

일반적으로 많이 사용하는 깊은 복사 방법인 스프레드 연산 (...) 를 통해 객체를 복사하면 깊은 복사가 되긴한다.

단, 객체 안 객체, 배열 안 배열은 깊은 복사 되지 않는다.

 

// 깊은 복사
let obj = {a:'a'}
let deepCopy = {...obj}

// nested object
let obj = {a:'a', nested:{b:'b'}}
let deepCopy = {...obj}
let deepCopy2 = {...obj}


deepCopy.nested.b = 'B';
deepCopy2.nested.b = 'C';

console.log(deepCopy.nested.b) // 'C' 
console.log(deepCopy2.nested.b) // 'C'

외부 라이브러리 없이 해결 방법으로는 

let deepCopy = JSON.parse(JSON.stringify(obj));

이 있다.

 

lodash 같은 라이브러리를 활용하면

import cloneDeep from 'lodash/cloneDeep';

let deepCopy = cloneDeep(obj)

도 가능하다.

'Javascript' 카테고리의 다른 글

Promise를 지원하지 않는 NPM 모듈 Promise로 변환  (0) 2023.04.14

Container / Presentation 방식

container : 데이터 조작을 다루는 컴포넌트

presentation : 화면을 다루는 컴포넌트

CRA는 NPX로

NPX는 그 순간 최신의  소스를 받아와서 설치 후 삭제함

NPM 전역으로 CRA를 설치후 CRA를 하면, 설치 당시의 버전으로 사용해야하고,

나중에 패키지가 업데이트 되면 새로 전역에 설치해야함

또, CRA의 의존성 패키지들을 로컬에 남겨두지 않음

React + type script

npx create-react-app my-app --template typescript

React에 typescript , scss 추가

yarn add -D typescript @types/node @types/react @types/react-dom @types/jest
yarn add sass

// tsconfig.js
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
  },
  "include": [
    "src"
  ]
}

React + eslint + prettier + redux tool-kit

yarn add -D prettier eslint-config-prettier eslint-plugin-prettier eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
yarn add @reduxjs/toolkit react-redux react-router-dom

// .eslintrc.js
module.exports = {
  env: {
    browser: true,
    node: true,
  },
  extends: [
    'prettier',
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
  },
  plugins: ['react', '@typescript-eslint'],
  rules: {
    'prettier/prettier': ['error', { endOfLine: 'auto' }],
  },
};

// .prettierrc.js
module.exports = {       
  // String is in single quotes (') 
  // 문자열은 홀따옴표(')로 
  singleQuote: true,
  // With a semicolon at the end of the code. 
  // 코드 마지막에 세미콜른이 있게 
  semi: true,
  // Do not use tabs and replace them with space bars. 
  // 탭의 사용을 금하고 스페이스바 사용으로 대체하게 
  useTabs: false,
  // Indentation width of 2 spaces 
  // 들여쓰기 너비는 2칸
  tabWidth: 2,
  // When you create an object or array, you also put a comma on the element or on the back of the key-value.
  // 객체나 배열을 작성 할 때, 원소 혹은 key-valueㅇ의 맨 뒤에 있는 것에도 쉼표를 붙임
  trailingComma: 'all',
  //One line of code is maximum 80 spaces 
  // 코드 한줄이 maximum 80칸
  printWidth: 80,
};

filter vs find

const item = productList.find((list: productListProps) => {
    return list.id === Number(id);
});
// 조건에 해당하는 요소 반환
const item2 = productList.filter((list: productListProps) => {  //
  return list.id === Number(id);
});
// 배열만들어서 만들어줌

React Query

yarn add react-query

//index.tsx
import { QueryClient, QueryClientProvider } from 'react-query';
const queryClient = new QueryClient();

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement,
);
root.render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <Provider store={store}>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </Provider>
    </QueryClientProvider>
  </React.StrictMode>,
);


// DashBoard.tsx 대쉬보드 컴포넌트
import axios from 'axios';
import { useQuery } from 'react-query';
import * as React from 'react';

const DashBoard = () => {
   const result = useQuery(
    '작명',
    () =>
      axios.get('https://codingapple1.github.io/userdata.json').then((a) => {
        return a.data;
      }),
    {
      refetchOnWindowFocus: false, // react-query는 사용자가 사용하는 윈도우가 다른 곳을 갔다가 다시 화면으로 돌아오면 이 함수를 재실행합니다. 그 재실행 여부 옵션 입니다.
      retry: 0, // 실패시 재호출 몇번 할지
      onSuccess: (data) => {
        // 성공시 호출
        console.log(data);
      },
      onError: (e) => {
        // 실패시 호출 (401, 404 같은 error가 아니라 정말 api 호출이 실패한 경우만 호출됩니다.)
        // 강제로 에러 발생시키려면 api단에서 throw Error 날립니다. (참조: https://react-query.tanstack.com/guides/query-functions#usage-with-fetch-and-other-clients-that-do-not-throw-by-default)
        console.log(e.message);
      },
    },
  );

  return (
    <div>
      {result.isLoading && '로딩중'}
      {result.error && '에러남'}
      {result.data && result.data.name}
    </div>
  );
};

export default DashBoard;

불변성 지키면서 배열 업데이트

let [users, setUsers] = useState([]);

# 배열에 추가
setUsers(users.concat(user));
# 배열에 추가 (함수형)
setUsers((prev) => prev.concat(user));

# 배열에서 삭제 
const onRemove = id => {
  // user.id 가 id 인 것을 제거
  setUsers(users.filter(user => user.id !== id));
};
 
#배열 수정
const onToggle = id => {
  setUsers(
    users.map(user =>
      user.id === id ? { ...user, active: !user.active } : user
    )
  );
};

불변성 지키면서 객체(object) 업데이트

#객체에 추가 #객체 업데이트
setUsers(state => {...state, key: value})

#객체에서 제거 #loadash
setUsers(state => {..._.omit(state, 'deleteKey')})

 

맨 아래로 Scroll 하기

messageListRef.current?.scrollTo(0, messageListRef.current.scrollHeight);

4 warnings generated.
  SOLINK_MODULE(target) Release/nodejavabridge_bindings.node
ld: warning: directory not found for option '-L/Library/Java/JavaVirtualMachines/adoptopenjdk-14.jdk/Contents/Home/lib/jli'
ld: library not found for -ljli
clang: error: linker command failed with exit code 1 (use -v to see invocation)

 

 

sudo npm install java --unsafe-perm=true --allow-root

ES6에서 $ 기호를 통해 변수를 쉽게 삽입할 수 있게 되었다.

예제를 통해 보자

 

let email = "abc@naver.com";

console.log("이메일은 " + email + "입니다"); //기존 따옴표 방법

console.log(`이메일은 ${email} 입니다`)  //new


console.log(`${5+10} 입니다`) //이런 것도 가능하다.

 

결과

아주 편리하다.

+ Recent posts