fix: React Refresh has trouble inferring router exports
This commit is contained in:
parent
b9dfea12d5
commit
7113d4db53
|
@ -4,6 +4,8 @@ import {
|
|||
RouterProvider,
|
||||
} from 'react-router-dom';
|
||||
|
||||
import {performReactRefresh} from 'react-refresh/runtime';
|
||||
|
||||
export const hooks = {
|
||||
'@flecks/core.hmr.hook': (hook, fleck, flecks) => {
|
||||
if ('@flecks/react/router.routes' === hook) {
|
||||
|
@ -48,17 +50,23 @@ export const mixin = (Flecks) => class FlecksWithReactRouterClient extends Fleck
|
|||
constructor(runtime) {
|
||||
super(runtime);
|
||||
const flecks = this;
|
||||
let debounceRefresh;
|
||||
this.reactRouter = {
|
||||
invalidate() {
|
||||
const {root} = flecks.get('@flecks/react/router');
|
||||
if (debounceRefresh) {
|
||||
return;
|
||||
}
|
||||
// Sorry.
|
||||
setTimeout(() => {
|
||||
debounceRefresh = setTimeout(() => {
|
||||
const {root} = flecks.get('@flecks/react/router');
|
||||
Promise.resolve(flecks.invokeFleck('@flecks/react/router.routes', root))
|
||||
.then((routes) => {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
this.router._internalSetRoutes(routes);
|
||||
performReactRefresh();
|
||||
debounceRefresh = undefined;
|
||||
});
|
||||
}, 20);
|
||||
}, 10);
|
||||
},
|
||||
router: undefined,
|
||||
};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import {resolve} from 'path';
|
||||
|
||||
import {register} from 'react-refresh/runtime';
|
||||
|
||||
function filePathToSegmentPath(path) {
|
||||
let localPath = path;
|
||||
let suffix = '';
|
||||
|
@ -34,16 +36,24 @@ export async function createRoutesFromFiletree({importer, paths, resolver}) {
|
|||
// Build initial router object.
|
||||
Object.entries(moduleMap)
|
||||
.map(([, paths]) => (
|
||||
// Second-longest: path without extension.
|
||||
paths
|
||||
.sort((l, r) => (l.length < r.length ? -1 : 1))
|
||||
.slice(0, -1)
|
||||
.pop()
|
||||
))
|
||||
.sort((l, r) => (l < r ? -1 : 1))
|
||||
.forEach((path) => {
|
||||
.map((path) => {
|
||||
let trimmed = path;
|
||||
// @todo dynamic
|
||||
const extensions = ['.jsx', '.js', '.tsx', '.ts', '.mdx'];
|
||||
const extension = extensions.find((ext) => path.endsWith(ext));
|
||||
if (extension) {
|
||||
trimmed = path.slice(0, -extension.length);
|
||||
}
|
||||
return [path, trimmed];
|
||||
})
|
||||
.forEach(([path, trimmed]) => {
|
||||
let walk = children;
|
||||
const parts = ['/', ...resolve('/', path).split('/').slice(1)];
|
||||
const parts = ['/', ...resolve('/', trimmed).split('/').slice(1)];
|
||||
const segments = parts.map(filePathToSegmentPath);
|
||||
for (let i = 0; i < segments.length; ++i) {
|
||||
const segment = segments[i];
|
||||
|
@ -90,6 +100,10 @@ export async function createRoutesFromFiletree({importer, paths, resolver}) {
|
|||
await Promise.all(
|
||||
elements.map(async ([children, node, path]) => {
|
||||
const route = await importer(path);
|
||||
// React Refresh has trouble inferring component types when modules are structured as React
|
||||
// Router prefers (e.g. `const export index = true` not being a component export). We'll give
|
||||
// it a helping hand.
|
||||
register(route, `${path} %exports%`);
|
||||
let {hoist} = route;
|
||||
if (hoist > 0) {
|
||||
const parts = node.path.split('/');
|
||||
|
@ -108,6 +122,11 @@ export async function createRoutesFromFiletree({importer, paths, resolver}) {
|
|||
case 'children':
|
||||
// ???
|
||||
return;
|
||||
case 'default':
|
||||
if (!route.Component) {
|
||||
node.Component = value;
|
||||
}
|
||||
return;
|
||||
case 'hoist':
|
||||
return;
|
||||
case 'index':
|
||||
|
|
Loading…
Reference in New Issue
Block a user