Skip to content

v1.7.0

Compare
Choose a tag to compare
@chaance chaance released this 25 Aug 19:09
· 3016 commits to main since this release

What's Changed

✨ Features

  • We removed our compiler's React shim in favor of esbuild's new automatic JSX transformation.

    There are no code changes required on your end, but by using the new transform we can prevent duplicate React imports from appearing in your build.

    The automatic JSX transform was introduced in React 17, and it allows you to write your JSX code without ever needing to import React. This means that compilers need to map JSX to React.createElement for you.

    Because esbuild previously didn't support this feature, we implemented a "shim" for the import to get the same affect. This unfortunately has caused problems with some external libraries, resulting in React being declared multiple times. (#2987)

    You still need to import modules from React that you use directly in your code (useState, useEffect, etc.). But if your component only needs the React import for JSX, you can safely omit it without worrying about duplicate imports.

  • The MetaFunction type can now infer data and parentsData types from route loaders.

    For example, if this meta function is exported from app/routes/sales/customers/$customerId:

    const meta: MetaFunction<
      typeof loader, // this will infer our type for `data`
      {
        root: RootLoader; // exported from the root route
        "routes/sales": SalesLoader; // exported from the sales route
        "routes/sales/customers": CustomersLoader; // exported from the sales/customers route
      }
    > = ({ data, parentsData }) => {
      ///
    };

    The meta function can be strongly typed by exposing each parent route's loader type:

    // app/root.tsx
    const loader = () => {
      return json({ hello: "world" } as const);
    };
    export type Loader = typeof loader;
    
    // app/routes/sales.tsx
    const loader = () => {
      return json({ salesCount: 1074 });
    };
    export type Loader = typeof loader;
    
    // app/routes/sales/customers.tsx
    const loader = () => {
      return json({ customerCount: 74 });
    };
    export type Loader = typeof loader;
    
    // app/routes/sales/customers/$customersId.tsx
    import type { Loader as RootLoader } from "~/root";
    import type { Loader as SalesLoader } from "~/routes/sales";
    import type { Loader as CustomersLoader } from "~/routes/sales/customers";
    
    const loader = () => {
      return json({ name: "Customer name" });
    };
    
    const meta: MetaFunction<
      typeof loader,
      {
        root: RootLoader;
        "routes/sales": SalesLoader;
        "routes/sales/customers": CustomersLoader;
      }
    > = ({ data, parentsData }) => {
      const { name } = data;
      //      ^? string
      const { customerCount } = parentsData["routes/sales/customers"];
      //      ^? number
      const { salesCount } = parentsData["routes/sales"];
      //      ^? number
      const { hello } = parentsData["root"];
      //      ^? "world"
    };
  • Each runtime package now exports a new type: SerializeFrom. This is used to infer the JSON-serialized return type of loaders and actions.

    type MyLoaderData = SerializeFrom<typeof loader>;
    type MyActionData = SerializeFrom<typeof action>;

Changes by package

New Contributors


Full Changelog: v1.6.8...v1.7.0