728x90

Can't use Watchman: "Operation not permitted"

 

Can't use Watchman: "Operation not permitted"

Since updating Watchman recently (with Homebrew) I can no longer use it to watch projects. I get { "version": "2022.05.30.00", "error": "std::__1::system_...

stackoverflow.com

watchman shutdown-server

로 해결

 

 

 

에러가 No bundle URL로 빨갛게 떴는데 

 

아래링크처럼

rm ios/build

로 삭제하고 

xcode에서 삭제해도 그대로 에러창 떴다. 

 

metro로 새로 뜨는 창에 

watchman 에러가 떠서 검색해보았다.

watchman 서버를 끄고 다시 실행하니까 잘 켜졌다. 

 

 

 

 

 

https://juzero-space.tistory.com/261

 

[React Native 에러 해결] IOS, No bundle URL present

1. 에러 상황 이유는 모르겠으나 No bundle URL present 에러가 발생했다. 아마 이것저것 만지다보니 나도 모르게 잘못 건드린거같다 ㅠ 2. 해결방법 해결방법이 간단하다. 다행.. 첫번째 방법) ios/build

juzero-space.tistory.com

 

 

728x90
728x90

미디어쿼리

max-width

최대여기 영역까지 css적용!

 

*그래서 순서도 큰 영역에서 작은 영역으로 써줘야 적용이 된다!!!!!!!

(이런느낌)

  @media screen and (max-width: 1440px) {
   
  }
  @media screen and (max-width: 1024px) {
   
  }

  @media screen and (max-width: 400px) {
   
  }

 

최소영역은 반대

작은 영역에서 큰영역으로 순서 써야함..

 

중앙정렬

중앙정렬할 때 

마진 오토가 안먹혀서 뭔가 했더니 가로값을 주어야했다!!

 position: fixed;
  /* fixed를 쓸 때에는 width, height를 명시해줘야 한다. */
  width: 460px
  /* left, right는 해당 요소의 위치 시작점을 결정한다. 그런데, 이때, margin의 양 값을 auto로 줌으로써 마진을 주어 해당 요소의 양 끝 위치를 각각 0으로 만들어준다. */
  margin: 0 auto;
  left: 0;
  right: 0;

출처 :https://wansook0316.github.io/dv/html-css/2020/03/19/position-fixed-center-%EC%A0%95%EB%A0%AC.html

 

////

position

postion: fixed

position:relative

position:absolute

....

https://developer.mozilla.org/ko/docs/Web/CSS/position

 

display:plex

 

 

 

728x90

'프론트 > Html Css' 카테고리의 다른 글

margin 값 방향  (0) 2021.10.26
box-sizing: border-box;  (0) 2021.10.26
box-shadow  (0) 2021.10.26
구조 가상 클래스 only-child /nth-of-type(n)  (0) 2021.08.23
:target :checked/ input type="checkbox"/필수입력창  (0) 2021.08.22
728x90

리액트 네이티브란?

페이스북에서 만든 오픈소스 모바일 애플리케이션 프레임워크이다.

 

HTML,CSS 대신 자바스크립트 스레드로 이뤄져 있다.

 

장점

 JavaScript를 사용하여 Android 와 iOS를  동시에 개발할 수 있어 효율적이다.

codePush를 통한 배포로 원하는 기능을 스토어를 거치지 않고 할 수 있다.

쉽고 빠른 UI 작성을 할 수 있다.

리액트 개발자가 사용하기 쉽다.

단점

성능이슈가 쉽게 나타나 낭비되는 렌더링을 확인해야 한다.

버그의 원인을 추적해나가는 과정이 다소 어렵다.

빌드타임이 오래 걸린다.

 

Windows, Linux 또는 Mac OS를 사용하여 React Native를 시작할 수 있습니다.

iOS 및 Android 환경은 Mac OS에서 모두 사용 가능하지만

Linux와 Windows는 Android 환경만 지원합니다.

React Native 개발을 위해 macOS를 사용한다고 하지만 Windows 및 Linux에서도

할 수 있다.

 

 

React Native 를 시작하는 두 가지 방법이 있다.

 

Expo CLI  

설치 및 배포가 쉬움 하지만 expo 라이브러리를 써야돼서 한정적일 수 있음

 

React Native CLI

설치해야되는 것들이 상대적으로 많음

 

 

 

 

expo란?

“create-react-native-app was replaced by expo-cli.”

Expo CLI는 개발자와 Expo 도구 간의 기본 인터페이스인 명령줄 앱입니다.

쉬운 앱개발을 할 수 있습니다.

Expo 는 ios, Android앱 개발할 수 있는 프레임워크이자 플랫폼이다

https://docs.expo.dev/workflow/expo-cli/

 

Expo CLI - Expo Documentation

Expo is an open-source platform for making universal native apps for Android, iOS, and the web with JavaScript and React.

docs.expo.dev

 

 

 

 

expo 설치 (with 타입스크립트)

 

Nodejs 가 설치되어있어야 한다.

 

npm install -g expo-cli

 

expo init 폴더명

cd 폴더명


npm start # you can also use: expo start

 

 

(expo 앱 깔아서 QR찍어서

핸드폰으로 연동해서 보면 되는데 

만약에 

android emulator로 보고 싶으면

 

Run on Android device/emulator 를 클릭하면, 자동으로 연결된다.

 

또는 터미널 상에서 a 버튼을 누르면 바로 실행된다.

Press a for Android emulator, or w to run on web.)

 

 

 

기존 프로젝트에 typescript 추가하기

npm install -D typescript @types/jest @types/react @types/react-native @types/react-test-renderer

 

참고 :

https://reactnative.dev/docs/typescript#adding-typescript-to-an-existing-project

 

Using TypeScript · React Native

TypeScript is a language which extends JavaScript by adding type definitions, much like Flow. While React Native is built in Flow, it supports both TypeScript and Flow by default.

reactnative.dev

 

 

TypeScript 구성 파일을 추가합니다. tsconfig.json프로젝트의 루트에 생성

{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"jsx": "react-native",
"lib": ["es2017"],
"moduleResolution": "node",
"noEmit": true,
"strict": true,
"target": "esnext"
},
"exclude": [
"node_modules",
"babel.config.js",
"metro.config.js",
"jest.config.js"
]
}

jest.config.jsTypeScript 사용하도록 Jest를 구성 하는 파일 만들기

module.exports = {
preset: 'react-native',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node']
};

JavaScript 파일의 이름을 다음과 같이 변경하십시오.*.tsx

./index.js은 그대로 두어야 한다. 그렇지 않으면 프로덕션 빌드 번들링과 관련하여 문제가 발생할 수 있습니다.

 

yarn tsc

새 TypeScript 파일을 유형 검사하려면 실행하십시오 .

(만약 안된다면  npm install typescript –g 로 전역설치

https://stackoverflow.com/questions/39404922/tsc-command-not-found-in-compiling-typescript)

 

'tsc command not found' in compiling typescript

I want to install typescript, so I used the following command: npm install -g typescript and test tsc --version, but it just show 'tsc command not found'. I have tried many ways as suggested in

stackoverflow.com

 

 

 

 

 

 

 

 

 

react native cli 설치

 

 

1.자바 설치 (JDK)  Java Downloads | Oracle

- “고급 시스템 설정”에서 환경변수 수정 (시스템속성->환경변수 -> 새로 만들기)

변수 이름 적고, 하단에는 설치한 폴더 경로 입력 후 확인.

-시스템 변수에서 path 클릭, 새로 만들기 클릭, %JAVA_HOME%\bin 입력후 확인

-명령 프롬프트 에

 

javac    (javac 명령오는 텍스트 파일로 작성된 java 파일을 bytecode로 컴파일함)

java-version 입력해 버전 값 나오는지 확인

 

 

 

 

2. 안드로이드 스튜디오 설치 및 환경설정 Download Android Studio and SDK tools  |  Android Developers

-Tools에서 SDK manager 들어가서 사용할 디바이스 선택 및 설치

-환경변수 수정

 

 

 

3. Nodejs 설치 Node.js (nodejs.org)

4. Python 설치 Download Python | Python.org

5. npx react-native init AwesomeProject  

(타입스크립트 템플릿 추가

npx react-native init AwesomeTSProject --template react-native-template-typescript

)

6. npx react-native start

7. npx react-native run-android (새 터미널 창에서 입력, npm run android 해도 됨)

 

 

참고(특히 환경변수 설정 참고~~!) : https://marshmello.tistory.com/69

 

React Native 설치 및 프로젝트 생성하기

저번글에서는 리액트 네이티브가 무엇인지 작성하였습니다. https://marshmello.tistory.com/68?category=1213283 이번글에서는 리액트 네이티브로 프로젝트를 생성해 보도록 하겠습니다. 1. 자바 설치 및 환

marshmello.tistory.com

https://reactnative.dev/docs/environment-setup

 

에러났을 때

-에러 SDK tool 안 깔려 있는 것이 없는지 확인

-경로 확인(환경변수 확인)

 

에러 

error failed to launch emulator. Reason:No emulators found as an output of `emulator -list-avds` 

 

Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'. > SDK location not found. Define location with an ANDROID_SDK_ROOT environment variable or by setting the sdk.dir path in your project's local properties file

해결

local.properties 파일 만들어서 해결

(sdk.dir=해당 경로 입력)

참고: https://healthcoding.tistory.com/35

https://eso0609.tistory.com/92 

https://stackoverflow.com/questions/59355688/how-to-solve-the-error-failed-to-launch-emulator-reason-no-emulators-found-as

 

How to solve the error, Failed to launch emulator. Reason: No emulators found as an output of `emulator -list-avds` in React nat

I am creating react native app for mobile application. I am fully new in building react native app. I am using ubuntu for creating the app and following below link to create the app. https://facebook.

stackoverflow.com

 

 

 

728x90
728x90

지난 시간,,,

https://stepby-yun.tistory.com/179

 

formData 이미지데이터 보내고 받기 (react,nodejs,header)

회원가입시 아이디 비번 프로필을 등록하려했다. id password는 넘겨주고 req.body.id로 받았는데 프로필은 formData 객체로 묶어서 그자체로 넘겨줬는데 자꾸 undefined 떴다. formData는 req.body가 안된다길

stepby-yun.tistory.com

formData 로 이미지 받는 걸 Header를 뒤늦게 추가해서 넣었다.

이제 mySQL 데이터베이스에 넣으려는데

아무것도 없고  BLOB만 달랑 저장됨

이미지 저장은 보통 BLOB로 한다고 해서 타입을 이렇게 넣었는데 

저렇게만 보이니 당황,, 

 

 

BLOB은 뭘까?

A Binary Large Object (BLOB) is a MySQL data type that can store binary data such as images, multimedia, and PDF files.

바이너리 데이터를 DB외부에 저장하기 위한 타입이다

"blob의 경우 4GB의 이진 데이터를 저장할 수 있다고 합니다. 하지만 이건 DB에 직접 저장하는 것이 아니라 DB에는 Large Object의 위치 포인터만 저장하게 됩니다."

그말은 즉, 컴퓨터가 인식하는 모든 파일(이진 데이터)를 저장하는 타입이라고 한다. 오 찾아보니까 볼 수 있긴하네

이렇게 확인할 수는 있구만 

 

 

하지만 BLOB보다는 URL자체로 저장을 선호한다고 한다.

그 이유는데이터베이스 서버는 애플리케이션이 확장될 때 종종 성능병목 현상이 일어나는데 이미지와 함께 로드하면 더 큰 병목현상이 발생한다고 함.

Many web app designers don't store images in database BLOBS, but rather store them in a file system, and store their URLs in database strings. Why? Database servers often become a performance bottleneck when an application scales up. If you load them with images, they'll become even bigger bottlenecks.

 

그럼 string문자열로 바꿔줘야지~

하고 string찾는데 없어 아 맞다 VAR이지하고 보다가

 

VARCHAR과 CHAR의 차이가 뭔가 궁금해졌다

VARCHAR은 '가변길이'

실질적인 데이터와 길이 정보도 같이 저장된다.

CHAR은 길이가 고정되어있어야한다. 남는 공간은 공백으로 채운다 공간낭비 발생!

VARCHAR is variable length, while CHAR is fixed length

https://petri.com/sql-server-string-data-types/

 

 

 

경로저장함

 

 

 

이제 id랑 password 도 함께 저장해봐야지 

 

 

 

 

 

 

출처

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=magnking&logNo=220950061851

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=rlasksdud53&logNo=220595010315

 

 

728x90
728x90

회원가입시

아이디 비번

프로필을 등록하려했다.

 

id password는 

넘겨주고 req.body.id로 받았는데 

프로필은 formData 객체로 묶어서 

그자체로 넘겨줬는데 자꾸 undefined 떴다. 

 

formData는 req.body가 안된다길래 

 

 

 

multer을 써봤는데도 안됨

(req.body대신 req.file 또는 files를 찍어봤지만 안됐다. )

 

formData쓸때 헤더에 타입을 넣어줘야한대서 

 

뒤늦게 

  {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      }

를 추가했다. 위치는 보내는 formdata 다음에 넣어줬다.

 

이걸로도 해결이 안됐는데 신기하게 

같이보낸 id, password를 지우니 

undefined가 안뜨고 이미지가 전송돼서 images폴더에 이미지도 담겼다!

 

req.file에 이미지url이 찍혔다.

 

import React, { useState } from "react";
import Axios from "axios";
import "./signup.css";
import FormData from "form-data";

function Signup() {
  //회원가입 값
  const [id, setId] = useState("");
  const [password, setPassword] = useState("");

  // const [imageUpload, setImageUpload] = useState(null);

  const [image, setImage] = useState({
    preview:
      "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAM1BMVEXk5ueutLfn6eqrsbTp6+zg4uOwtrnJzc/j5earsbW0uby4vcDQ09XGyszU19jd3+G/xMamCvwDAAAFLklEQVR4nO2d2bLbIAxAbYE3sDH//7WFbPfexG4MiCAcnWmnrzkjIRaD2jQMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMw5wQkHJczewxZh2lhNK/CBOQo1n0JIT74/H/qMV0Z7GU3aCcVPuEE1XDCtVLAhgtpme7H0s1N1U7QjO0L8F7llzGeh1hEG/8Lo7TUmmuSrOfns9xnGXpXxsONPpA/B6OqqstjC6Ax/0ujkNdYQQbKNi2k64qiiEZ+ohi35X+2YcZw/WujmslYewiAliVYrxgJYrdwUmwXsU+RdApUi83oNIE27YvrfB/ZPg8+BJETXnqh9CVzBbTQHgojgiCvtqU9thFJg/CKz3VIMKMEkIXxIWqIpIg2SkjYj+xC816mrJae2aiWGykxRNsW0UwiJghJDljYI5CD8GRiCtIsJxizYUPQ2pzItZy5pcisTRdk/a9m4amtNNfBuQkdVhSaYqfpNTSFGfb9GRIakrE2Pm+GFLaCQPqiu0OpWP+HMPQQcgQMiQprWXNmsVwIjQjYi/ZrhAqNTCgr2gu0Jnz85RSSjso0HkMFZ0YZjKkc26a/jlmh9JiDyDxi9oeorTYAzZkwwoMz19pzj9bnH/GP/+qbchjSGflneWYhtTuKdMOmNKZcJ5TjInQKcYXnESd/jQxy0ENpULTNGOGgxpap/oyw9pbUAqhfx2Dbkhovvfgz4iUzoM9+GlK6/Mh4q29hyC1mwro30hpVVLPF9wYQr71RazOeM5/cw81iBRD+A03aM9/C/obbrKjbYSpCmIVG3qT/Q8oeUo3Rz0IL7vI1tEbCB9pSiu8I/aV8x3Kg/BGWrWp4ZVs0nZfmAoEG4h/61yHYIJiFSl6Q0Vk6tTW1N8kYp8hdOkfHYYMXd2Qft+8CYwqYDSKvqIh+MCF8Wgca2u/cwdgeW3TtuVn6+1oBs3yLo5C2JpK6CvQzGpfUkz9UG/87gCsi5o2LIXolxN0FbwAsjOLEr+YJmXn7iR6N0BCt5p5cMxm7eAsfS+/CACQf4CTpKjzgkvr2cVarVTf96372yut7XLJ1sa7lv6VcfgYrWaxqr3Wlo1S6pvStr22sxOtTNPLzdY3nj20bPP+ejFdJYkLsjGLdtPBEbe/mr2bQKiXWJDroA+vtzc0p9aahuwqHMDYrQEXHEw9jwQl3drMpts9JBU1SdktPe5FBRdJQ6bwXBpa57ib2A8kukQDzMjh++Uo7Fo6Wd02Pkf4fknqoo4HtvAIjsqUcjx6DIPgWCaOML9rKI/oqD9/lgNrn+eF+p7j8tnzHBiR7+kdUGw/+V1Kzkc75mMy6U+FMaxjPibiM1U1uGM+puInHpmALZCgP4pt7i840MV8+0R1zPsRB6UTcqpizncYwZ89syDydfyWCwXB1l8/zRNGWbTG/GHKUm9AkxHMc/EGSk3z2+ArEhPEV5TUBLEvUGFcjEUH80J/jveTGOAJEljJbILWGQT3zRYiwuKsUXN1EEJAzBhRJFll7mBUG7KD8EqPkKekBREaL8hMDZLQSG6AQjtHPYmvTQnX0TtpC1SYCe2YdkkyLP3jj5BSbKiuR585eQhTgoje6yIb0Yb0C+mV6EYvebqw5SDy2WmubogZiF2AVxPC2FpDf8H2Q9QWo6IkjUxTWVEI3WY/wrCeSuqJ+eRWzXR/JXwgVjUMozbCOfoEZiSiKVGepqv5CJ8RyR4D7xBeamqa7z3BJ/z17JxuBPdv93d/a2Ki878MMAzDMAzDMAzDMAzDMF/KP09VUmxBAiI3AAAAAElFTkSuQmCC",
    data: "",
    // Headers: " 'Content-Type': 'multipart/form-data'",
  });

  //다 userlist에 담아서 db저장하기
  // const [userList, setUserList] = useState([]);

  const onChangeId = (event) => {
    setId(event.target.value);
  };

  const onChagePassword = (event) => {
    setPassword(event.target.value);
  };

  const Submit = (e) => {
    e.preventDefault();

    let formData = new FormData();
    formData.append("file", image.data);

    console.log(image.data, "선택한이미지! ");
    console.log(formData, "들어가기전폼데이터");

    Axios.post(
      "http://localhost:3001/submit",

      // {
      //   id: id,
      //   password: password,
      //   formData,
      //   headers: { "Content-Type": "application/x-www-form-urlencoded" },
      // }
      // {
      //   id: id,
      //   password: password,
      // },

      formData,

      {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      }
    ).then(() =>
      console.log(
        formData,
        "then이후 폼데이터",
        image,
        "이건뭐",
        image.data,
        "이미지데이터"
      )
    );
  };

  const handleFileChange = (e) => {
    const img = {
      preview: URL.createObjectURL(e.target.files[0]),
      data: e.target.files[0],
    };

    setImage(img);
  };

  return (
    <div className="formBox">
      <div className="signup_id">
        <input placeholder="아이디" onChange={onChangeId}></input>
      </div>
      <div className="signup_password">
        <input placeholder="비밀번호" onChange={onChagePassword}></input>
      </div>
      <div>
        <input placeholder="비밀번호 확인"></input>
      </div>
      {image.preview && <img src={image.preview} width="100" height="100" />}
      <input
        type="file"
        onChange={handleFileChange}
        name="Images"
        accept="Images/*"
      />

      <button onClick={Submit}>제출</button>
    </div>
  );
}

export default Signup;

 

 

 

const express = require("express");
const app = express();

const mysql = require("mysql");
const cors = require("cors");
const multer = require("multer");
const path = require("path");
app.use(cors());

app.use(express.json());
//이거 필요한거임?
app.use(express.static("Images"));

const db = mysql.createConnection({
  user: "*",
  host: "*",
  password: "*",
  database: "*",
});

const upload = multer({
  storage: multer.diskStorage({
    destination: function (req, file, cb) {
      cb(null, "Images/");
    },
    filename: function (req, file, cb) {
      cb(null, new Date().valueOf() + path.extname(file.originalname));
    },
  }),
});
// const upload = multer({
//   dest: "Images/",
//   limits: { fileSize: 5 * 1024 * 1024 },
// });

// app.post("/up", upload.array("img"), (req, res) => {
//   console.log(req.files);
// });

app.post("/submit", upload.single("file"), (req, res) => {
  console.log(req.files, "레큐파일ㄴ");
  console.log(req.body, "레큐바디");
  // console.log(req.body, "레큐바디");
  // const id = req.body.id;
  // const password = req.body.password;
  const profile = req.file;

  console.log(req.file, "파일");
  // res.json({ url: `/img/${req.file.filename}` });
  // FormData의 경우 req로 부터 데이터를 얻을수 없다.
  // upload 핸들러(multer)를 통해서 데이터를 읽을 수 있다

  //   function insertRecord(req, res) {
  // req.files.forEach((e) => {
  // // console.log(e.filename);
  // // });
  // console.log(req.file, "파일");
  // console.log(profile, "이미지");

  db.query(
    "INSERT INTO userlist (userProfile) VALUES (?) ",
    [profile],
    (err, result) => {
      if (err) {
        console.log(err);
      } else {
        res.send("userlist values inserted");
      }
    }
  );
});

app.listen(3001, () => {
  console.log("your server is running on 3001~! yeah");
});

 

문제는 id랑 password를 빼고 보내서 그런지 

 

Error: ER_WRONG_VALUE_COUNT_ON_ROW: Column count doesn't match value count at row 1

오류: ER_WRONG_VALUE_COUNT_ON_ROW:  개수가  1  개수와 일치하지 않습니다.

이게 뜬다

 

아직 db저장도 안됐고 해결안된게 많지만 이미지를 받아서 행복함...

id랑 password를 같이 받으면 왜 undefined로 뜨는걸까?

따로 해야되는것인가..

 

 

 

아무튼 

header의 역할 ,context Type에 대해 공부하고

https://jw910911.tistory.com/117

formData(json으로 변환하라는 얘기도 있던데...나는 그거 안되던데..왜지?), multer

에 대해 더 공부하고 정리해봐야겠다.

+

app/router차이도 헷갈리니까 확인해놓자.

http://expressjs.com/ko/guide/routing.html

express가져와서 app으로 선언해서 썼는데 검색하다가 코드보면 express.router로 쓰는 게 무슨 차인가 싶어서..

728x90
728x90

노마드코더 강의 보는중

 

리액트 네이티브는 브라우저가 없음, 웹사이트가 아니야!

 

앱개발하는데 필요한 java 등등 깔아줄게 많음

 

그래서 강의에서는 네이티브 코드 바로 시작할 수 있게 expo 써서 한다.

핸드폰에 expo앱깔면 연동으로 보이네 신기하다

(expo 설치 내용 https://docs.expo.dev/)

 

( https://snack.expo.dev/ 여기서 작업하면 visual studio도 필요없고 node, npm 설치 안했어도 바로 테스트할 수 있음)

 

 

리액트 네이티브는 웹사이트가 아님!

HTML이 아니기 때문에 div쓸 수 없음

대신에 view를 씀 얘는 container컨테이너다 (react Native에서 import해와야 쓸 수 있음!)

(The most fundamental component for building UI, View is a container that supports layout with flexbox, style, some touch handling,,,)

 

react native에 있는 모든 텍스트는 text component안에 들어가야한다

border css는 사용불가능하다

 

처음에 react Native는 많은 컴포넌트와 API를 지원했는데 버그많고 비효율적이어서 

빠르게 만드는데 초첨맞추고 두 개를 축소시킴

 

(components와 API의 차이는 무엇인가?>

components는 화면에 렌더링할 항목이다

API는 (운영체제와 소통하는) 자바스크립트 코드이다)

 

reactNative 커뮤니티에서 쓸 수도 있지만

expo가 우리에게 필요한 Package를 제공한다.  https://docs.expo.dev/versions/v44.0.0/sdk/async-storage/

 

여기서는 이미 container View가 Flew container다

모바일에서는 Flex direction 기본값이 colum(열-세로)

(원래 웹에서는 Flex direction 기본값이 Row(행-가로) 였음)

 

레이아웃에서 대부분 width, height안씀. 반응형 페이지 생각해야함!!! 매번화면 달라지는데말여

React Native에서는 flex 비율로 레이아웃 채워서 씀

 

 

 

728x90
728x90

결론>

헤더와 푸터를 만들기 위해서 컴포넌트를 만들었는데

헤더랑 푸터 스크립트 안에 또 <Header/>로 컴포넌트 부르고 있어서 그랬다.

 

 

삽질>

캐시 지우고 

 

컴퓨터 고급 설정으로 메모리 더 사용하게 바꾸고

 

더 큰 메모리 할당하는 방법, 옵션 주는 것도 해봤는데 안됐다. 

 

728x90
728x90

따라하면서

순서, 필요한 내용 적기 

<이 순간, 최고의 강의_별점 백개 드립니다_>

https://www.youtube.com/watch?v=re3OIOr9dJI 

 

client -react 프론트

server -express, 백단

 

client/ npx create-react-app .

(.은 현재 위치를 의미함)

server/ npm init 

해서 package.json 생성하고

필요한 

mysql express 

설치

 

client/

Login.js

import { useState } from "react";
import "./login.css";

function Login() {
  const [name, setName] = useState("");
  const [age, setAge] = useState(0);
  const [country, setCountry] = useState("");
  const [position, setPosition] = useState("");
  const [wage, setWage] = useState(0);

  const onChangefun = (event) => {
    setName(event.target.value);
    console.log(event.target.value);
  };
  return (
    <div className="login">
      <div className="information">
        <label>Name : </label>
        <input type="text" onChange={onChangefun}></input>
        <label>Age : </label>
        <input
          type="number"
          onChange={(event) => {
            setAge(event.target.value);
          }}
        ></input>
        <label>Country : </label>
        <input
          type="text"
          onChange={(event) => {
            setCountry(event.target.value);
          }}
        ></input>
        <label>Position : </label>
        <input
          type="text"
          onChange={(event) => {
            setPosition(event.target.value);
          }}
        ></input>
        <label>Wage: </label>
        <input
          type="number"
          onChange={(event) => {
            setWage(event.target.value);
          }}
        ></input>
        <button>직원 등록</button>
      </div>
    </div>
  );
}

export default Login;

 

server/

index.js

const express = require("express");
const app = express();

app.listen(3001, () => {
  console.log("your server is running on 3001~! yeah");
});

 

이제 mysql 설정해줄거임

 

mysql 워크벤치에서 

스키마 생성

테이블 생성

server/

디비저장 코드 입력

 

const express = require("express");
const app = express();
const mysql = require("mysql");

const db = mysql.createConnection({
  user: "root",
  host: "localhost",
  password: "비밀번호",
  database: "crudtest",
});

app.post("/create", (req, res) => {
  const name = req.body.frontname;
  const age = req.body.frontage;
  const country = req.body.frontcountry;
  const position = req.body.frontposition;
  const wage = req.body.frontwage;

  db.query(
    "INSERT INTO employees (name, age, country, position, wage) VALUES (?,?,?,?,?)",
    [name, age, country, position, wage],
    //콜백함수
    (err, result) => {
      if (err) {
        console.log(err);
      } else {
        res.send("values Inserted");
      }
    }
  );
});

app.listen(3001, () => {
  console.log("your server is running on 3001~! yeah");
});

client/

import { useState } from "react";
import "./login.css";
import Axios from "axios";

function Login() {
  const [name, setName] = useState("");
  const [age, setAge] = useState(0);
  const [country, setCountry] = useState("");
  const [position, setPosition] = useState("");
  const [wage, setWage] = useState(0);

  const addEmployee = () => {
    Axios.post("http://localhost:3001/create", {
      frontname: name,
      frontage: age,
      frontcountry: country,
      frontposition: position,
      frontwage: wage,
    }).then(() => {
      console.log("success");
    });
  };

  const onChangefun = (event) => {
    setName(event.target.value);
    console.log(event.target.value);
  };
  return (
    <div className="login">
      <div className="information">
        <label>Name : </label>
        <input type="text" onChange={onChangefun}></input>
        <label>Age : </label>
        <input
          type="number"
          onChange={(event) => {
            setAge(event.target.value);
          }}
        ></input>
        <label>Country : </label>
        <input
          type="text"
          onChange={(event) => {
            setCountry(event.target.value);
          }}
        ></input>
        <label>Position : </label>
        <input
          type="text"
          onChange={(event) => {
            setPosition(event.target.value);
          }}
        ></input>
        <label>Wage: </label>
        <input
          type="number"
          onChange={(event) => {
            setWage(event.target.value);
          }}
        ></input>
        <button onClick={addEmployee}>직원 등록</button>
      </div>
    </div>
  );
}

export default Login;

프런트에서 백 전달할때 

우리는 api허용해주기 위해서 cors 라이브러리 사용할거임

npm i cors

 

server/ index.js 파일에

const cors = require("cors");
app.use(cors());

추가

 

 

 

 

근데 여전히 막상보면 백으로 못넘어옴

이렇게 req.body 콘솔 찍어보면 

undefined 뜸 

 

json 미들웨어를 제공안해서였음

프런트에서 보낼때 

 

 

index.js/

app.use(express.json());

이거 추가

 

유튜브영상에서는 이거 추가하면 db넣기 성공했는데 난 안됨. ㅎ

 

 db에 안들어가고 

에러 뜸

Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client

 

 

이거 mysql에 외부접근안돼서 그런거라고 함  

그래서 이걸로 해결가능하다고 함( 비번 사용해서 db계정사용하게끔 하는 설정인듯!)

 

+해결방법중에 mysql2쓰는 것도 있음 이번에는 안해봄 

 ALTER user '[유저]'@'localhost' IDENTIFIED WITH mysql_native_password by '[비번]';

 바꿔주기 위해서 mysql로 ㄱㄱ

mysql에 바로 use mysql하면 접속이 안됨

mysql -u root -p도 당연히 안됨

 

 

'use'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는
배치 파일이 아닙니다

워크벤치 경로로 들어가서 해야함~~~

C:\Program Files\MySQL\MySQL Server 8.0\bin

 

 

cd C:\Program Files\MySQL\MySQL Server 8.0\bin

mysql -u root -p

 

이제 mysql켜짐

 

mysql>

 

 

계정 뭐있는지 확인 먼저 함

 

SELECT user,authentication_string,plugin,host FROM mysql.user;

 

내가 쓸 root계정 있는거 확인함

 

 

 

 

 ALTER user '[유저]'@'localhost' IDENTIFIED WITH mysql_native_password by '[비번]';

 

flush privileges;

 

 

 

index.js 

서버 끄고 다시 실행

node index.js

로 실행

 

 

직원등록 눌러서 보내보면 

 

잘 들어왔다~!~!~!~!~!

 

 

 

이제 우리가 할거는

백-> 프런트로 

정보 가져오는걸 할거임

우리는 필요할 때 정보를 봐야하니까 

 

 

client/

//초기에는 빈배열이니까 []로 넣어줌 
 const [employeesList, setEmployeesList] = useState([]);
 //가져올 함수// 백가져온 응답반은걸 콘솔로 보여주겠음 response가져온거의 data로
   const getEmployee = () => {
    Axios.get("http://localhost:3001/employees").then((response) => {
      setEmployeesList(response.data);
    });
  };
  
  
 //버튼
   <div className="showDB">
      //버튼눌렀을 때 가져올 함수 실행
        <button className="showDB-button" onClick={getEmployee}>
          show employees
        </button>
      </div>

 

server/

app.get("/employees", (req, res) => {
//db에서 employess테이블 다 가져와
  db.query("SELECT * FROM employees", (err, result) => {
    if (err) {
      console.log(err);
    } else {
      res.send(result);
    }
  });
});

버튼 누르면

이건 response임 

object 객체로 가져옴

(status 200 -> 작동한거임)

이안에 우리가 원하는 정보가 잘 담겨져있음

 

 

이제 백에서 가져온 것들을 화면에 띄워줄거임

맵함수 사용해서

배열에서 하나씩 꺼내오기 

 

        <div>
          {employeesList.map((val, index) => {
            return (
              <div className="employee">
                <h3>{val.name}</h3>
                <h3>{val.age}</h3>
                <h3>{val.country}</h3>
                <h3>{val.position}</h3>
                <h3>{val.wage}</h3>
              </div>
            );
          })}
        </div>

성공~~~

 

 

근데 다른 방법도 있대 

post에 넣고 바로 화면에 띄우게 하는법

 

const addEmployee = () => {
    console.log(name, "dfdfd");
    Axios.post("http://localhost:3001/create", {
      frontname: name,
      frontage: age,
      frontcountry: country,
      frontposition: position,
      frontwage: wage,
    }).then(
      //   () => {
      //   console.log("success");
      // }
      () => {
        //기존 배열에 방금 입력한 걸 추가하고 그걸 setEmployessList함수에 넣음! 배경은 뜨는데 값이 안띄워지네..흠
        //암튼 여러 방법이 있다고 함 있다가 해보자
        setEmployeesList([
          ...employeesList,
          {
            frontname: name,
            frontage: age,
            frontcountry: country,
            frontposition: position,
            frontwage: wage,
          },
        ]);
      }
    );
  };

나는 왜인지 빈값만 뜸

 

db에는 잘들어갔는데...

왜 안뜨는 것인가...

이부분은 다른 날에 해보겟음

 

 

이제 

삭제 하고 수정하고 다음에 해봐야지

db에서 가져온 목록 선택해서 나열하게 하고

이런 것도 해보고 싶네 

 

아 그리고 지금은 새로고침하면 db에서 블러온 애들이 화면에서 사라지거든

그것도 막아야겠다.

728x90
728x90

state변경할 때 모든 code들은 항상 다시 실행됨

근데 api가져와서 쓸때를 예를 들면 매번 다시 가져오면 번거로워지지

 

몇몇 코드를 처음에 딱 한번만 실행되고 다시 실행안되게 하고 싶음

 

useEffect(우리가 실행시킬함수,[변경되는지 지켜볼애])

 

 

 

 

처음 렌더링됐을 때 한번만 실행되고

버튼 눌러서 state바뀔 때 실행되지 않음

 


+코드제어

 

클릭할때 keyword 검색코드 다시 실행안되게 막기

키워드를 검색할 때만 실행되게 하기

[keyword]로 넣어서 이 keyword  state값이 변경될때만 이 코드 실행됨

조건으로 keyword가 비어있고 keyword길이가 5이상일때만 실행되게 하였음

 

 

 

처음에는 실행안됐고

검색창에 6자넣으니까 실행됨 

 

 

 

---

[] 아무것도 지켜보지 않거나

[keyword] 키워드 변경하는지 보거나

[keyword, counter] 둘다 변경하는지 보거나 (둘중 하나 변경될때 실행)

이렇게 쓸 수 있음

728x90
728x90

https://react.vlpt.us/mashup-todolist/01-create-components.html

 

1. 컴포넌트 만들기 · GitBook

1. 컴포넌트 만들기 투두리스트의 기능을 구현하기 전에, 우리 프로젝트에서 필요한 모든 컴포넌트들의 UI 를 미리 만들어보겠습니다. 우선 create-react-app 을 사용하여 새로운 프로젝트를 만들어

react.vlpt.us

이거 보고 투두리스트 만드는 중인데 

 

  Line 4:10:  'MdDone' is defined but never used    no-unused-vars
  Line 4:18:  'MdDelete' is defined but never used  no-unused-vars

 

 

컴포넌트만 생성하고 안에 변수 안넣어서 안뜨는 거였다!ㅎㅎㅎ삽질좋아

이전
넣어주니
잘뜸

아까는 

 

모듈문제인 주 알고 react-icon 다시깔고 그랬네

그거 다시 까니까 styled-component 모듈 찾을 수 없대서 또 다시깔았어..

 

(참고로 투두리스트 시작할때 styled-component모듈 깔아도 안된다길래 뭐지 했는데 

버전 문제였음 5.0.0로 하니까 잘되더라. 이놈의 버전에러)

yarn add styled-components@5.0.0

 

 

모듈깔때 다른 것도 삭제되기도 하나보네 

그것만 삭제하고 다시 깔아야되는데 그냥 해서 그런가..

 

 


 

 

한번에 이렇게 스타일 여러 개 줄 수 있는 거 좋다

 

 


 

컴포넌트를  app.js말고

다른 컴포넌트 안에 넣는 경우도 있는데 만들면서 경로 잘봐야겠다!!

 

얘를 들면 Todolist 에 들어가는 TodoItem 같은 경우

728x90
728x90

https://ko.reactjs.org/docs/hooks-state.html 에서 발췌

 

Hook이란?

React의 useState Hook을 사용해봅시다!

 

 

Hook이란? Hook은 특별한 함수입니다. 예를 들어 useState는 state를 함수 컴포넌트 안에서 사용할 수 있게 해줍니다. 다른 Hook들은 나중에 살펴봅시다!

언제 Hook을 사용할까? 함수 컴포넌트를 사용하던 중 state를 추가하고 싶을 때 클래스 컴포넌트로 바꾸곤 했을 겁니다. 하지만 이제 함수 컴포넌트 안에서 Hook을 이용하여 state를 사용할 수 있습니다.

 

state 변수 선언하기

클래스를 사용할 때, constructor 안에서 this.state를 { count: 0 }로 설정함으로써 count를 0으로 초기화했습니다.

함수 컴포넌트는 this를 가질 수 없기 때문에 this.state를 할당하거나 읽을 수 없습니다. 대신, useState Hook을 직접 컴포넌트에 호출합니다.

 

useState를 호출하는 것은 무엇을 하는 걸까요? “state 변수”를 선언할 수 있습니다. 위에 선언한 변수는 count라고 부르지만 banana처럼 아무 이름으로 지어도 됩니다. useState는 클래스 컴포넌트의 this.state가 제공하는 기능과 똑같습니다. 일반적으로 일반 변수는 함수가 끝날 때 사라지지만, state 변수는 React에 의해 사라지지 않습니다.

useState의 인자로 무엇을 넘겨주어야 할까요? useState()Hook의 인자로 넘겨주는 값은 state의 초기 값. 함수 컴포넌트의 state는 클래스와 달리 객체일 필요는 없고, 숫자 타입과 문자 타입을 가질 수 있습니다. 위의 예시는 사용자가 버튼을 얼마나 많이 클릭했는지 알기를 원하므로 0을 해당 state의 초기 값으로 선언했습니다. (2개의 다른 변수를 저장하기를 원한다면 useState()를 두 번 호출해야 합니다.)

useState는 무엇을 반환할까요? state 변수, 해당 변수를 갱신할 수 있는 함수 이 두 가지 쌍을 반환합니다. 이것이 바로 const [count, setCount] = useState()라고 쓰는 이유입니다. 클래스 컴포넌트의 this.state.count와 this.setState와 유사합니다. 

이제 useState를 이용하여 많은 것을 만들 수 있습니다.

 

count라고 부르는 state 변수를 선언하고 0으로 초기화합니다. React는 해당 변수를 리렌더링할 때 기억하고, 가장 최근에 갱신된 값을 제공합니다. count 변수의 값을 갱신하려면 setCount를 호출하면 됩니다.

 

import React, { useState } from "react";
//여기서 useState가 Hook

//https://ko.reactjs.org/docs/hooks-overview.html

//버튼클릭시 값 증가

function Example() {
  //'count'라는 새 상태 변수를 선언
  //0은 초기값
  const [count, setCount] = useState(0);
  //하나의 컴포넌트 내에서 State Hook을 여러 개 사용할 수 있음
  const [age, setAge] = useState(10);
  const [fruit, setFruit] = useState("banana");
  //   const [toDos, setToDos] = useState([{ text: "Learn Hooks" }]);  //여기

  return (
    <div>
      <p>You clicked {count}times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <h3>나이{age}살부터 사용가능</h3>
      <button onClick={() => setAge(age * 2)}>Click me</button>
      <h3>우리가 먹을 과일은:{fruit}</h3>
      <button onClick={() => setFruit(fruit + "apple")}>과일추가</button>
      {/* <h3>뭔데 넌{toDos}</h3>
      <button onClick={() => setToDos(toDos + "add")}>텍스트추가요</button> 여기추가하면 왜안되지*/}
    </div>
  );
}

export default Example;

왜 저 todos는 안될까 에러떠

혹시 카멜표기 때문인가 싶어서 대문자 넣어봤는데 아니더라고

✌️ Hook 사용 규칙

Hook은 그냥 JavaScript 함수이지만, 두 가지 규칙을 준수해야 합니다.

  • 최상위(at the top level)에서만 Hook을 호출해야 합니다. 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하지 마세요.
  • React 함수 컴포넌트 내에서만 Hook을 호출해야 합니다. 일반 JavaScript 함수에서는 Hook을 호출해서는 안 됩니다. (Hook을 호출할 수 있는 곳이 딱 한 군데 더 있습니다. 바로 직접 작성한 custom Hook 내입니다. 이것에 대해서는 나중에 알아보겠습니다~~~)
728x90

+ Recent posts