v1.7.0
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 inferdata
andparentsData
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
@remix-run/cloudflare
@remix-run/deno
@remix-run/dev
@remix-run/node
@remix-run/react
@remix-run/serve
@remix-run/server-runtime
New Contributors
- @philandstuff made their first contribution in #3939
- @maxprilutskiy made their first contribution in #3944
- @willin made their first contribution in #3957
- @joelazar made their first contribution in #3902
- @arnaudambro made their first contribution in #3953
- @redabacha made their first contribution in #3889
- @andreiduca made their first contribution in #3985
- @justinwaite made their first contribution in #3989
- @n8agrin made their first contribution in #4001
Full Changelog: v1.6.8...v1.7.0