上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

【Remix教程翻译】开发者博客(二)

[复制链接]
  • TA的每日心情
    擦汗
    4 天前
  • 签到天数: 194 天

    [LV.7]常住居民III

    720

    主题

    6071

    回帖

    6850

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6850

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2022-11-27 18:36:02 | 显示全部楼层 | 阅读模式

    添加TypeScript支持

    import { json } from "@remix-run/node";
    import { Link, useLoaderData } from "@remix-run/react";
    
    type Post = {
      slug: string;
      title: string;
    };
    
    type LoaderData = {
      posts: Array<Post>;
    };
    
    export const loader = async () => {
      return json<LoaderData>({
        posts: [
          {
            slug: "my-first-post",
            title: "My First Post",
          },
          {
            slug: "90s-mixtape",
            title: "A Mixtape I Made Just For You",
          },
        ],
      });
    };
    
    export default function Posts() {
      const { posts } = useLoaderData() as LoaderData;
      return (
        <main>
          <h1>Posts</h1>
          <ul>
            {posts.map((post) => (
              <li key={post.slug}>
                <Link
                  to={post.slug}
                  className="text-blue-600 underline"
                >
                  {post.title}
                </Link>
              </li>
            ))}
          </ul>
        </main>
      );
    }

    在json里添加了一个LoaderData的接口
    这部分Ts还是比较简单的,有兴趣自己查查
    但是如果在useLoaderData后边不设置 as LoaderData就会出现any类型
    所以我们在读取数据的时候又设置了一下any

    补充

    在loader里的json函数是为了在响应数据的时候创建一个application/json头,并假定你使用了utf-8编码
    关于这部分可以参考代码

    const json = (data, init = {}) => {
      let responseInit = typeof init === "number" ? {
        status: init
      } : init;
      let headers = new Headers(responseInit.headers);
    
      if (!headers.has("Content-Type")) {
        headers.set("Content-Type", "application/json; charset=utf-8");
      }
    
      return new Response(JSON.stringify(data), { ...responseInit,
        headers
      });
    };
    

    补充完毕

    当设置好TS类型后,即使通过网络请求读取数据,也可以获得类型的安全性,因为在同一个文件定义,除非在读取数据的时候崩溃,否则在组件和API中都具有类型安全性。

    一点点的重构

    一个可靠的办法就是创建一个处理特定问题的模块,在例子中,将阅读和攥写帖子,现在让我们新建一个模块,然后增加getPosts函数,并将他导出
    创建app/models/post.server.ts
    粘贴内容

    type Post = {
      slug: string;
      title: string;
    };
    
    export async function getPosts(): Promise<Array<Post>> {
      return [
        {
          slug: "my-first-post",
          title: "My First Post",
        },
        {
          slug: "90s-mixtape",
          title: "A Mixtape I Made Just For You",
        },
      ];
    }
    

    这里虽然没有使用任何异步,但是使用了async,说明以后你可以在这里使用
    因为async返回Promise,所以类型提示是

    Promise<Array<Post>>

    接下来在
    app\routes\posts\index.tsx
    更新代码为

    import { getPosts } from "~/models/post.server";
    
    type LoaderData = {
      // this is a handy way to say: "posts is whatever type getPosts resolves to"
      posts: Awaited<ReturnType<typeof getPosts>>;
    };
    
    export const loader = async () => {
      return json<LoaderData>({
        posts: await getPosts(),
      });
    };

    这里的

     Awaited<ReturnType<typeof getPosts>>

    算是一个难点
    getPosts是一个函数
    首席按typeof获取他的类型
    得到
    ()=>Promise<Post[]>
    然后使用ReturnType得到一个函数的返回类型推断
    也就是Promise<Post[]>
    Awaited类似于await,会递归取得嵌套在promise的类型
    可以参考https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html
    也就是说最后得到了Post[]作为返回类型
    那么说白了

    type LoaderData = {
      // this is a handy way to say: "posts is whatever type getPosts resolves to"
      posts: Awaited<ReturnType<typeof getPosts>>;
    };
    这段代码
    也就是
    type LoaderData = {
      posts: Post[];
    };
    罢了

    那官方课程第一篇的一半已经结束后,后续涉及Prisma~

    结语

    撒花~

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表