ryu110
@ryu110

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Graphqlでデータを取得したい

Discussion

GraphQLで単一のデータが取れません。
リストで全てのデータは取れますが1つのデータだけを取ることができません。
どこを改善すればよいでしょうか?

type Post {
    id: Int
    title: String!
    content:String!
  }
  type Query {
    allPosts: [Post!]!
    singleDetail(id:Int!): Post!
  }

Query: {
    allPosts: () => {
      return prisma.post.findMany();
    },
    singleDetail: (args:any) => {
      return prisma.post.findUnique({
        where:{
          id:args.post.id
        },
        select:{
          id:true,
          title:true,
          content:true,
        }
      })
    },
  },

0

とりあえずGraphqlのQueryのsingleDetailの返り値の型は[Post!]!ではなくPost!ではないでしょうか。singleDetailを実行した際に型エラーになっていませんか?

0Like

idがundefindになっていました。Post!に変更してgrapqiQLで見ていますがidが見つからないと出てしまいます。

query singleDetail {
  singleDetail(id: 8) {
    id
    content
    title
  }
}
0Like

Postのidをnot nullにしてみてください。Int -> Int!

type Post {
    id: Int!
    title: String!
    content:String!
  }
0Like

クエリの返り値からid外して実行すればとりあえず実行できるようにはなるはずです(根本的な解決ではないですが)

query singleDetail {
  singleDetail(id: 8) {
    content
    title
  }
}
0Like

Type missは無くなりましたが
id undefindeです

message: "Cannot read property 'id' of undefined"
path: ["singleDetail"]
0: "singleDetail"
0Like

現在こんな感じです
[back]

import express from "express";
import cors from "cors";
import { PrismaClient } from "@prisma/client";
import { graphqlHTTP } from "express-graphql";
import { makeExecutableSchema } from "@graphql-tools/schema";

export interface Context {
  prisma: PrismaClient;
}

const prisma = new PrismaClient();

const typeDefs = `
  type User {
    id:Int!
    name: String
    email: String!
  }
  type Post {
    id: Int!
    title: String!
    content:String!
  }
  type Query {
    allUsers: [User!]!
    allPosts: [Post!]!
    singleDetail(id:Int): Post!
  }
  type Mutation {
    createPost(
      title: String!
      content:String!
      ):Post!
    deletePost(
      id: Int
      ):Post!
    createUser(
      name: String
      email:String!
      ):User!
  }
`;

type argsPostType = {
  title: string;
  content: string;
};
type argsDeletePostType = {
  id: number;
};
// type argsDetailPostType = {
//  authorId: number;
//   id: number;
//   title: string;
//   content: string;
// };
type argsUserType = {
  name: string;
  email: string;
};

const resolvers = {
  Query: {
    allUsers: () => {
      return prisma.user.findMany();
    },
    allPosts: () => {
      return prisma.post.findMany();
    },
    singleDetail: (args:any) => {
      return prisma.post.findUnique({
        where:{
          id:args.post.id
        },
        select:{
          id:true,
          title:true,
          content:true,
        }
      })
    },
  },
  Mutation: {
    createPost: (parent: any, args: argsPostType, context: any, info: any) => {
      const newPost = prisma.post.create({
        data: {
          title: args.title,
          content: args.content,
          author: {
            connect: {
              id: 1,
            },
          },
          published: true,
        },
      });
      return newPost;
    },
    deletePost: (
      parent: any,
      args: argsDeletePostType,
      context: any,
      info: any
    ) => {
      const deletedPost = prisma.user.update({
        where: {
          id: 1,
        },
        data: {
          posts: {
            delete: {
              id: args.id,
            },
          },
        },
      });
      return deletedPost;
    },
    createUser: (parent: any, args: argsUserType, context: any, info: any) => {
      const newUser = prisma.user.create({
        data: {
          name: args.name,
          email: args.email,
        },
      });
      return newUser;
    },
  },
};

export const schema = makeExecutableSchema({
  resolvers,
  typeDefs,
});

const app = express();
app.use(cors());
app.use(
  "/graphql",
  graphqlHTTP({
    schema,
    graphiql: true,
  })
);

if (process.env.NODE_ENV !== "production") {
  require("dotenv").config();
}

const PORT = process.env.PORT || 3001;

app.listen(PORT, () => {
  console.log(`接続完了! ${PORT}.`);
});

[front]
省略しています

const detailPostButton = ({id}:{id:number}) => SinglePostShow({id})
<NavLink to={`/AllPostsShow/${id}`}>
 <Button onClick={() => detailPostButton({id})}>
    詳細
</Button>
</NavLink>

button押した後に遷移するところ

import { useQuery, gql } from '@apollo/client'
// import { useParams } from 'react-router-dom'


export const SINGLE_POST_DETAIL = gql`
query singleDetail($id: Int) {
  singleDetail(id: $id) {
    id
    title
    content
  }
}
`

export const SinglePostShow = ({id}:{id:number}) => {
  const {
    data: single_post_detail,
    loading: post_loading,
    error: post_error,
  } = useQuery(SINGLE_POST_DETAIL)

  if (post_loading) return <p>Loading...</p>
  if (post_error) return <p>Error...</p>
  return (
    <div key={id}>
      詳細フォーム
      <input>{single_post_detail.title}</input>
    <input>{single_post_detail.content}</input>
    </div>
  )
}

export default SinglePostShow

0Like

おそらく下記のargs.post.idの部分が参照エラーになっていると思います。GraphQLのエラーではなくjavascriptのエラーです。id:args.post.idの部分をとりあえず決め打ちでid:8args?.post?.id || 8などのようにして実行して動作するか確認してみてください。問題なく動作するのであれば、引数argsにちゃんと値が渡されているのか、構造がどうなっているのか確認してください。

Query: {
    allPosts: () => {
      return prisma.post.findMany();
    },
    singleDetail: (args:any) => {
      return prisma.post.findUnique({
        where:{
          id:args.post.id
        },
        select:{
          id:true,
          title:true,
          content:true,
        }
      })
    },
  },
0Like

query singleDetail {
singleDetail(id: 8) {
content
title
}
}
をしてもエラーになりますね。
Cannot read property 'post' of undefinedがでてきます・・・

0Like

そこじゃないです。
javascriptかtypescriptか分かりませんがprismaのfindUniqueの中のidの部分です。ここのargs.post.idでundefinedエラーが出ているはずです。とりあえず決め打ちでid:8とかにしてやってみてください

return prisma.post.findUnique({
        where:{
          id:args.post.id
        },
        select:{
          id:true,
          title:true,
          content:true,
        }
      })
0Like

rgs?.post?.id || 9にして動かしたら画面は出てきましたがなぜがinputの中にデータが出てきません。これはおかしいでしょうか?

スクリーンショット (120).png

0Like

データは取れているみたいです。
あとはデータ取得後のコードの部分がうまくいっていないと思われます。

0Like

ちなみにargs?.post?.id || 9にしたらなぜ動くのかというと、単純にargs?.post?.idがundefinedだったら9を参照するようにしているだけなので、根本的な解決はしていません。引数argsからちゃんとidを取得できるようにコードを書き直す必要があります。console.logしながら見ていくといいです。

0Like

今問題なのはargs.post.idではidを取得できない

 where:{
          id:args.post.id
 },

とFrontでのコードで正しくtitle、contentを画面表示できていないということですね

0Like

そうなります。

  • graphqlのスキーマに問題はない
  • データベースとの通信も問題ない
  • prismaの使い方も問題ない

問題なのは

  • args.post.idの書き方がおかしい。これに関してはconsole.log(args)などで中身を見ながら書き直してみてください。
  • Frontのコードについては、申し訳ありませんが私はインフラや機械学習のエンジニアなのでちょっとわからないです。
0Like

button押したときにはidが渡ってきているのですがその後undefindなんですよね

0Like

Your answer might help someone💌