728x90
반응형
setState({
      ...state,
      [e.target.id]: { ...state[e.target.id], [e.target.name]: e.target.value },
    });

위와 같은 방식으로 사용하고자 할 때, typescript에서 에러가 발생할 경우가 있다.

그럴 땐아래 코드를 인터페이스에 추가해주자.

 

interface abc  {
    [prop: string]: any;
}
728x90
반응형
728x90
반응형

Grid container 과 같은 mui에서 자체적으로 사용하는 props를 styled로 사용하는 방법은 다음과 같다.

이 방법만 알아도 왠만한 css는 정리가 가능할 것이다.

const GridContainer = styled((props) => <Grid container {...props} />) <any>`
    width: ${(props) => props.width || `100%`};
    height: ${(props) => props.height};
`

 

- 예시 전체 코드

import { Grid } from '@mui/material'
import { GetServerSideProps, NextPage } from 'next'
import { styled } from '@mui/material/styles'

const GridContainer = styled((props) => <Grid container {...props} />) <any>`
    width: ${(props) => props.width || `100%`};
    height: ${(props) => props.height};
`

const GridItem = styled((props) => <Grid item {...props} />) <any>`
    width: ${(props) => props.width || `100%`};
    height: ${(props) => props.height};
`

const Login: NextPage = () => {
    return (
        <>
            <GridContainer height={"300px"} >
            </GridContainer>
            <GridContainer height={"300px"} >
                <GridItem xs={12}>
                    <GridContainer
                        direction={"row"}
                    >
                        <GridItem xs={4}>
                            a
                        </GridItem>
                        <GridItem xs={4}>
                            b
                        </GridItem>
                        <GridItem xs={4}>
                            c
                        </GridItem>
                    </GridContainer>
                </GridItem>
            </GridContainer>
        </>
    )
}

export default Login;


export const getServerSideProps: GetServerSideProps = async (context) => {

    return {
        props: {
        },
    };
}

 

참고로 모듈로 styled 파일을 따로 빼둘 때에는 tsx 확장자로 해야한다.

728x90
반응형
728x90
반응형

.babelrc 에 { "runtime" : "automatic" } 추가

 - 전체코드 

{
    "presets": [
        "next/babel",
        [
            "@babel/preset-env",
            {
                "targets": {
                    "chrome": "91",
                    "firefox": "89"
                }
            }
        ],
        [
            "@babel/preset-react",
            {
                "runtime": "automatic"
            }
        ]
    ],
    "plugins": [
        "@emotion"
    ]
}
728x90
반응형
728x90
반응형

해당 에러는 vscode의 typescript와 로컬 typescript의 버전이 맞지 않아서 생긴다.

 

1. vscode의 settings.json 파일에 다음을 추가해준다.

작업 영역의 루트 폴더에서 해야한다. 경로 안의 프로젝트에 typescript를 설치했다면 경로를 인식하지 못한다.

또한 로컬 내에 타입스크립트의 버전과 vscode 타입스크립트의 버전을 꼭 확인해야한다.

{
	"typescript.tsdk": "node_modules/typescript/lib"
}

그 다음 vscode를 껐다 키고 f1을 누르면

이렇게 나오는데, 두 번째 작업 영역 버전을 사용하면 된다.

728x90
반응형
728x90
반응형

기존 js로 되어있던 프로젝트를 typescript로 변경해야 될 때가 있다.

 

1. 필요한 패키지 다운로드

$ npm i typescript ts-loader @types/node @types/react @types/react-dom @types/jest --dev

2. tsc 명령어 안먹힘

window로 작업하던 중 tsc 명령어가 안 먹히는 것을 보고 해결법을 찾았다. 아래와 같은 오류일 때 가능하다.

tsc : 'tsc' 용어가 cmdlet, 함수, 스크립트 파일 또는 실행할 수 있는 프로그램 이름으로 인식되지 않습니다. 
 이름이 정확한지 확인하고 경로가 포함된 경우 경로가 올바른지 검증한 다음 다시 시도하십시오.

 

window 파워 셀을 관리자 권한으로 실행한 뒤 권한을 RemoteSigned로 바꿔준다.

 

3. tsconfig.json 파일 생성

tsc --init 명령어로 tsconfig.json 파일을 만든 뒤에 다음과 같이 작성한다. 옵션을 꼭 따라할 필요는 없다.

{
  "compileOnSave": true,
  "compilerOptions": {
    "target": "es2016",
    "jsx": "react-jsx",
    "module": "esnext",
    "sourceMap": true,
    "removeComments": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "noFallthroughCasesInSwitch": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": false
  },
  "include": [
    "./src/*"
  ],
  "exclude": [
    "node_modules/*"
  ]
}

 

4. webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.ts',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

기존 webpack 파일에 필요한 부분을 채워넣어준다.

 

혹시 기존에 babel 을 사용하고 있었다면 .babelrc 파일에 아래를 추가하고

"preset" : ["@babel/preset-typescript"]

webpack 파일에 다음을 추가해주자.

      {
        test: /\.(ts|js)x?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },

 

4. 컴파일

$ tsc

 

혹시 컴파일 시 결과를 터미널에서 알고 싶을 때는 tsconfig.json 폴더에서 noemit 부분을 false로 바꿔준다.

컴파일 하고 Cannot write file '경로' because it would overwrite input file.

이런 에러가 뜬다면

{
  "compilerOptions": {
    "outDir": "build",
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "build/**/*"]
}

outDir 폴더를 만들어주고, exclude 시켜준다.

 

tsc 명령어로 에러가 안뜬다면 webpack을 실행해준다.

$ npx webpack

 

참고로 tsc 다음에 파일 명을 쓴다면 tsconfig.json이 안먹힌다!

5. can only be default-imported using the 'esModuleInterop' flag

위와 같은 에러가 뜬다면 tsconfig.json 파일에 "esModuleInterop": true, 속성을 추가해주자.

기존 CommonJS 모듈을 ES6모듈 사양을 준수하여 가져올 수 있게 된다.

728x90
반응형
728x90
반응형

레거시 코드를 빌드하는데 에러가 떠버렸다.

누가 짰는진 모르겠지만 이 코드는 답이 없었다...

 

일단 오늘 빌드를 무조건 해야하는 상황이라 확실한 방법은 나중에 찾아봐야겠다.

다음 주부터 처음부터 다시 만들어야겠다.

module.exports = {
    webpack: (config, { isServer }) => {
        if (!isServer) {
             config.resolve.fallback.fs = false
             config.resolve.fallback.dns = false
             config.resolve.fallback.net = false
        }

        return config;
    }
}
728x90
반응형
728x90
반응형

개요

React 로 개발을 하면서 프론트 서버가 가끔 강제 종료되는 일이 자주 발생했다.
JavaScript heap out of memory 라고 오류 메세지가 출력 되는데
이유를 살펴보니 node.js가 과도하게 메모리 점유를 해서 발생한다.
해결 방법으로 더 큰 메모리를 할당 해 주면 된다고 하여 8GB를 할당 해 주었다.

해결 1

할당 해주는 방법은
터미널에

export NODE_OPTIONS="--max-old-space-size=8192"

위 코드를 입력해주면 해결 된다.

하지만 대부분 1시간을 버티지 못하도 다시 서버가 강제 종료 되었다.

알고 보니 너무 많이 할당을 해주어도 문제이다.

내 노트북은 8gb 램인데 다 할당을 해주니 다른 프로그램이 할당 받을 것을 다 뺏어버린 것이다.
결국 충돌로 꺼지게 된다는것을 알게 되었다.
과유 불급이었다.

해결 2

그래서 1gb부터 8gb까지 1기가씩 증가시켜서 램을 할당 해주니 3gb가 딱 적당했다.
export NODE_OPTIONS="--max-old-space-size=3072"

나는 이 오류로 2달을 고생했다. 지금이라도 고쳐서 다행이다.
구글링으로 알기 어려우니 글을 남겨서 다른 사람들도 램을 적당히 할당해주길 바란다.

1gb ~ 8gb

1GB ~ 8GB 할당 명령어

#1gb
export NODE_OPTIONS="--max-old-space-size=1024"

#2gb
export NODE_OPTIONS="--max-old-space-size=2048"

#3gb
export NODE_OPTIONS="--max-old-space-size=3072"

#4gb
export NODE_OPTIONS="--max-old-space-size=4096"

#5gb
export NODE_OPTIONS="--max-old-space-size=5120"

#6gb
export NODE_OPTIONS="--max-old-space-size=6144"

#7gb
export NODE_OPTIONS="--max-old-space-size=7168"

#8gb 
export NODE_OPTIONS="--max-old-space-size=8192"

8gb 이상 할당은 해주지 말자.
gb계산이 귀찮으니 위 코드를 복붙해서 사용하길 바란다.

etc

CRA가 아닌 node에서 발생해도 해결이 가능하다.

 
728x90
반응형
728x90
반응형

React에서는 줄바꿈을 허용하지 않는다. 때문에 매핑하고 <br /> 태그를 임의로 주어서 줄바꿈을 표기해주자.

 

<Wrap ai={`start`} margin={`25px 0 0 0`}>
                {state.post_content.split("\n").map((line: any) => { //this.props.data.content: 내용
                  return (
                    <span>
                      {line}
                      <br />
                    </span>
                  );
                })}
              </Wrap>

 

728x90
반응형
728x90
반응형
// 스크롤이 50px 이상 내려올경우 true값을 넣어줄 useState
const [scroll, setScroll] = useState(false);

useEffect(() => {
    window.addEventListener('scroll', handleScroll);
    return () => {
      window.removeEventListener('scroll', handleScroll); //clean up
    };
  }, []);

const handleScroll = () => {
	console.log("window.scrollY : ", window.scrollY)
  };

 

기준점을 잡고 현재 상태에서 올라갔는지 내려갔는지를 보려면 state가 아닌 일반 변수를 써야한다.

var scroll = 0;
    useEffect(() => {
        window.addEventListener('scroll', () => {
            // 검색등을 한 뒤 스크롤이 맨 위일 때는 임의로 컴포넌트를 보여주게 함.
            if (window.scrollY === 0) {
                dispatch({ name: "scrollUp", value: true })
            }
            // 스크롤이 맨 마지막에 도달했을 때
            else {
                if (Math.round(document.documentElement.scrollTop + window.innerHeight) - document.body.scrollHeight > -10) {
                    dispatch({ name: "scrollUp", value: false });
                }
                else if ((window.scrollY) < 10) {
                    dispatch({ name: "scrollUp", value: true });
                }
                else {
                    if (scroll < window.scrollY) {
                        dispatch({ name: "scrollUp", value: false });
                    }
                    else {
                        dispatch({ name: "scrollUp", value: true });
                    }
                }
            }

            scroll = window.scrollY;
        });
    }, []);
728x90
반응형
728x90
반응형
const beforeMinute = (date: any) => {
    const today = new Date();
    const timeValue = new Date(date);

    const betweenTime = Math.floor((today.getTime() - timeValue.getTime()) / 1000 / 60);
    if (betweenTime < 1) return '방금전';
    if (betweenTime < 60) {
        return `${betweenTime}분전`;
    }

    const betweenTimeHour = Math.floor(betweenTime / 60);
    if (betweenTimeHour < 24) {
        return `${betweenTimeHour}시간전`;
    }

    const betweenTimeDay = Math.floor(betweenTime / 60 / 24);
    if (betweenTimeDay < 365) {
        return `${betweenTimeDay}일전`;
    }

    return date;
}

 

const stringEllipsis = (str: string) => {
    let length = 30; // 표시할 글자수 기준
    if (str.length > length) {
        str = str.substring(0, length - 2) + '...';
    }
    return str;
}
728x90
반응형

+ Recent posts