Day 34


Graphqlエンティティ
Graphsqlも実はRest-api??
rest-apiを使うタイミングを考えてみましょう
投稿の表示:axios.get(APIアドレス)
投稿登録:axios.past(APIアドレス、{データ})
apiアドレスをendpointと呼びます
どこで見ましたか.

https://koreanjson.com/で練習した時もゴールを書きました.
各apiを作成するときに、バックエンドを作成するときに各apiが関数であることを覚えておきます(デバッグ時)(わあ!)

では,ユーザ登録api=ユーザ登録関数と理解できる.しかし、ここで発生した問題はアドレスが多すぎることです(端点が多すぎます!)

問題を解決する人
1つのエンドポイント+を作成してPostに設定するだけで、登録のようにデータを送信できますよね?そしてapiに巨大な関数を作成し、そこに適切な関数を作成すればいいのではないでしょうか.
/graphql{key : mutation createBoard{...}}
これにより、巨大な関数で適切な関数を実行できます.
掲示板の作成->api
変異だけでなく、同じ方法でクエリーを行うことができます.
複数のアドレス+対応するapiを統合
しかし、アドレス(端点)はgraphqlに変換され、その作用方式は同じrest-apiである.
!! 1.Graphqlは端点が1のrest-apiです!
!! 2.よく郵送する
練習する
postmanで練習
に従う

バックエンドへのアクセス
postの選択、アドレスの追加、raw-JSONの選択
{
	"query" : "query fetchBoards { fetchBoards {_id, writer, title, contents} }"
	
}

fetchでもmutationでもデータが含まれているのでPostでなければなりません

(表示されてよかった)
登録して

前のqueryはただのキーで、私たちが知っているキーではありません.
vsコードでも見てみましょう
import axios from "axios";
//         axios.post("", {}, { headers: {}}) 헤더를 넣는다면 이렇게 넣을것

export default function GraphqlRestPage() {
  async function onClickSubmit() {
    const result = await axios.post(
      "http://backend04.codebootcamp.co.kr/graphql",
      {
        query: `
        mutation createBoard {
          createBoard(
              createBoardInput:{
                  writer: "철수",
                  password: "1234"
                  title: "제목"
                  contents: "내용"
              }
          ){
              _id
              writer
          }
         }
          `,
      }
    );
    console.log(result);
  }
  return (
    <>
      <button onClick={onClickSubmit}>등록하기</button>
    </>
  );
}

コンソールも実際の上昇を見ることができます.
(実際の更新)
何をするにもPOST機能、REST-APIを利用して書かれています.
Optimistic UI楽観UI

フェイスブックで「いいね」を押すと必ずDBにいいけど早く見える
成功すると確信しているので、stateに入れてからリクエストします.
しかし、条件があります.
1.ワークロードの少ないAPI
2.99%以上の成功API
3.失敗しても傷つかないAPI
->ワークロードが少なく安定したAPIのみ
実際のコードで実装
import { gql, useMutation, useQuery } from "@apollo/client";
import {
  IMutation,
  IMutationLikeBoardArgs,
  IQuery,
  IQueryFetchBoardArgs,
} from "../../src/commons/types/generated/types";

const LIKE_BOARD = gql`
  mutation likeBoard($boardId: ID!) {
    likeBoard(boardId: $boardId)
  }
`;
const FETCH_BOARD = gql`
  query fetchBoard($boardId: ID!) {
    fetchBoard(boardId: $boardId) {
      _id
      likeCount
    }
  }
`;

export default function OptimisticUIPage() {
  const [likeBoard] = useMutation<
    Pick<IMutation, "likeBoard">,
    IMutationLikeBoardArgs
  >(LIKE_BOARD);
  const { data } = useQuery<Pick<IQuery, "fetchBoard">, IQueryFetchBoardArgs>(
    FETCH_BOARD,
    {
      variables: { boardId: "61bab569717be5002baa75a8" },
    }
  );
  function onClickOptimisticUi() {
    // 여기서 좋아요 증가시키는 mutation
    likeBoard({
      variables: { boardId: "61bab569717be5002baa75a8" },
    });
  }
  return (
    <>
      <div>좋아요 갯수 : {data?.fetchBoard.likeCount}</div>
      <button onClick={onClickOptimisticUi}>좋아요 올리기</button>
    </>
  );
}

FetchBoardで賛数を入力し、ハードコーディングでIDを入力しました.
個数はデータの中のfetchBoardの中のlikeCountです
以前は、賛数を増やしてrefetchを修正することで再ロードされていました.
  function onClickOptimisticUi() {
    // 여기서 좋아요 증가시키는 mutation
    likeBoard({
      variables: { boardId: "61bab569717be5002baa75a8" },
      refetchQueries: [
        {
          query: FETCH_BOARD,
          variables: { boardId: "61bab569717be5002baa75a8" },
        },
      ],
    });
こうすべきだ
これでは、取り戻されるまで待ちます.
しかし賛のように軽くて、重要ではありませんて、速いものが必要で、DBに更新するまで待つ必要はありません.
どうやって適用しますか?
optimisticResponseに設定し、
updateを使用してcacheを変更し、ターゲットはdataです.
cahe.writeQueryによるキャッシュの変更
queryはFETCH BOARDです.
変数は、どの投稿を区別できます.
次にdataに置換する情報を入力します
再整理すると.
LikeBoard apiリクエスト、変数付き
そして、OptimisticResponseに送信する前に、データを入れる(likeCount).
変更したデータをcacheに挿入し、更新を送信します.
偽応答修正+真修正、キャッシュ更新2回相当
?? 2回更新するのは効率的ではないでしょうか.
->私たちの目には、ずっと速く見えます.

人為的にネットの速度を調整することができます.
開発者ツール-ネットワーク-マスクは調整できます.
遅い3 Gは遅いです.(ロード時は無制限、カウントチェック時は速度制限)
そうすると、速度がずっと下がります.
コミットされたWebサイトを作成しましょう.
import { gql, useMutation } from "@apollo/client";
import { Modal } from "antd";
import { ChangeEvent, useCallback, useState } from "react";

const CREATE_BOARD = gql`
  mutation createBoard($createBoardInput: CreateBoardInput!) {
    createBoard(createBoardInput: $createBoardInput) {
      _id
      writer
      title
      contents
    }
  }
`;

const inputsInit = {
  writer: "",
  password: "",
  title: "",
  contents: "",
};

export default function IsSubmittingPage() {
  const [inputs, setInputs] = useState(inputsInit);
  const [createBoard] = useMutation(CREATE_BOARD);
  const onChangeInputs = useCallback(
    (name: string) => (event: ChangeEvent<HTMLInputElement>) => {
      setInputs((prev) => ({
        ...prev,
        [name]: event.target.value,
      }));
    },
    []
  );

  async function onClickSubmit() {
    try {
      const result = await createBoard({
        variables: {
          createBoardInput: { ...inputs },
        },
      });
      console.log(result);
      Modal.confirm({ content: "등록에 성공하였습니다." });
    } catch (error) {
      Modal.error({ content: error.message });
    }
  }

  return (
    <>
      작성자 <input type="text" onChange={onChangeInputs("writer")} />
      <br />
      비밀번호 <input type="password" onChange={onChangeInputs("password")} />
      <br />
      제목 <input type="text" onChange={onChangeInputs("title")} />
      <br />
      내용 <input type="text" onChange={onChangeInputs("contents")} />
      <br />
      <button onClick={onClickSubmit}>등록하기</button>
    </>
  );
}
UserCallbackまで使用しているので少し複雑になります

数回押すと何度も要求を出す
修正すると?

issubmittingstateを作成し、デフォルトfalseに設定し、コミット時にtrue、その後falseにします.そしてボタンにも障害者が取り付けられています.
森特里?
https://sentry.io/welcome/
docs - next.に入る
インストールコマンドを表示できます
yarn add @sentry/nextjs
その後のapp.tsxを設定する必要があります.

import+SENTRY DSNを設定する必要があります
DSNはプロジェクト-クライアントキー

コードにも適用されます.適用するインデックスに移動します.
import、新しいエラーを投げ出す(「強制的にエラーが発生する」);
sentry.captureException(error)
import { gql, useMutation } from "@apollo/client";
import { Modal } from "antd";
import { formatStrategyKeys } from "rc-tree-select/lib/utils/strategyUtil";
import { ChangeEvent, useCallback, useState } from "react";
import { useForm } from "react-hook-form";
import * as Sentry from "@sentry/nextjs";

const CREATE_BOARD = gql`
  mutation createBoard($createBoardInput: CreateBoardInput!) {
    createBoard(createBoardInput: $createBoardInput) {
      _id
      writer
      title
      contents
    }
  }
`;

const inputsInit = {
  writer: "",
  password: "",
  title: "",
  contents: "",
};

export default function IsSubmittingPage() {
  // const { formStage } = useForm()
  // formatStrategyKeys.isSubmitting // 리액트 훅폼의 모습
  const [inputs, setInputs] = useState(inputsInit);
  const [createBoard] = useMutation(CREATE_BOARD);
  const [isSubmitting, SetIsSubmitting] = useState(false);
  const onChangeInputs = useCallback(
    (name: string) => (event: ChangeEvent<HTMLInputElement>) => {
      setInputs((prev) => ({
        ...prev,
        [name]: event.target.value,
      }));
    },
    []
  );

  async function onClickSubmit() {
    SetIsSubmitting(true);
    try {
      throw new Error("에러 강제로 발생시킴");
      // const result = await createBoard({
      //   variables: {
      //     createBoardInput: { ...inputs },
      //   },
      // });
      // console.log(result);
      // Modal.confirm({ content: "등록에 성공하였습니다." });
      // SetIsSubmitting(false);
    } catch (error) {
      Modal.error({ content: error.message });
      Sentry.captureException(error);
    }
  }

  return (
    <>
      작성자 <input type="text" onChange={onChangeInputs("writer")} />
      <br />
      비밀번호 <input type="password" onChange={onChangeInputs("password")} />
      <br />
      제목 <input type="text" onChange={onChangeInputs("title")} />
      <br />
      내용 <input type="text" onChange={onChangeInputs("contents")} />
      <br />
      <button onClick={onClickSubmit} disabled={isSubmitting}>
        등록하기
      </button>
    </>
  );
}

エラーが発生しました.

ホットスポットが見えます.
サマリ
graphqlも事実postの端点を用いたrest-apiである.
次にOptimistic uiを使用します
issubmtting/センター信頼性の向上
1回のみ/自動トレースエラー
サービスが大きくなると、私たちは自分の哨兵を作成しますが、その前にこのサービスを使用します.