728x90

Unhandled Runtime Error

Error: Objects are not valid as a React child (found: object with keys {findFirstTransaction}). If you meant to render a collection of children, use an array instead.

 

 

 

const check = () =>{

const { loading, error, data } = useQuery(CHECK_WITHDRAW, {
    variables: {
    
    },
  })


return (
<>{data}</>
)



}

data가 객체여서 뜨는 에러!!!

 

JSON.stringfy(data, undefined, 2)

 

하면 잘뜨는거 확인할 수 있음!

 

usequery는 렌더될 때 바로 실행돼서

버튼 할때만 하는 useLazyquery로 수정해야겠다...

둘의 차이는 자꾸 까먹으니까 정리해라 네네~

 

 

https://velog.io/@leehyunho2001/React-Query%EC%97%90%EC%84%9C-%EB%B2%84%ED%8A%BC-%ED%81%B4%EB%A6%AD%EC%8B%9C%EC%97%90-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%9A%94%EC%B2%AD%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-feat.-useQuery

 

728x90
728x90

axios는

지원하는 브라우저가 더 많고 

에러핸들링이 좋고

자동으로 데이터가 json형태로 되어 넘어간다

Automatic JSON data transformation

As we saw earlier, Axios automatically stringifies the data when sending requests (though you can override the default behavior and define a different transformation mechanism). When using fetch(), however, you’d have to do it manually.

Compare:

// axios
axios.get('https://api.github.com/orgs/axios')
  .then(response => {
    console.log(response.data);
  }, error => {
    console.log(error);
  });

// fetch()
fetch('https://api.github.com/orgs/axios')
  .then(response => response.json())    // one extra step
  .then(data => {
    console.log(data) 
  })
  .catch(error => console.error(error));

fetch는 직접 json화를 해줘야하지만

지원하는 브라우저 문제 등을 충분히  해결할 수 있다.

 

 

결론

Axios는 대부분의 HTTP통신 요구사항을 위해 컴팩트 패키지로 사용하기 쉬운 API를 제공한다.

하지만 fetch()메소드를 사용해서도 Axios 라이브러리의 주요기능을 완벽하게 재현할 수 있다.

는 글

https://blog.logrocket.com/axios-vs-fetch-best-http-requests/

 

Axios vs. fetch(): Which is best for making HTTP requests? - LogRocket Blog

Axios is not always an ideal solution; depending on your needs, there are sometimes better options for making HTTP requests. The Fetch API is one of them.

blog.logrocket.com

 

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

이더리움 P2P(peer to peer) 네트워크는 두가지 요소로 구성되어 있다. 

  • 이더리움 클라이언트 (런타임 시 작동하며 네 가지 요소를 포함한다.)

-이더리움 가상머신 EVM ethereum virtual machine

-메모리 풀

노드가 수신한 거래내역을 네트워크에 전파하기 전에 저장한다. 투표 앱에서는 사용자가 제출한 투표 내역을 저장한다.

-클라이언트 프로세스

수신된 메시지 및 거래내역을 적절하게 EVM에 보내거나 거래내역을 메모리 풀에 저장하고 검색한다. 또한 피어 노드에서 받은 블록을 처리하고 블록체인 데이터베이스의 로컬 복사본에 추가한다.

-JSON-RPC API 

다른 노드나 외부에서 클라이언트의 기능을 사용할 수 있게 한다.

 

  • 블록체인 데이터베이스

유권자가 제출한 투표와 같은 거래 내역 외에도 블록체인은 네트워크 상에 배포된 모든 스마트 컨트랙트의 EVM 바이트 코드 복사본과 상태를 저장하고 있다. 채굴노드는 15초마다 정기적으로 새로운 블록을 불록체인에 추가한다.

 

설명 출처: <이더리움 디앱 개발>, 로베르토 인판테 지음, p70

728x90

+ Recent posts