Skip to content

Instantly share code, notes, and snippets.

@AlexandrHoroshih
Last active April 24, 2024 05:13
Show Gist options
  • Save AlexandrHoroshih/231b6c22608e1e1baafa1f8c69a4ab02 to your computer and use it in GitHub Desktop.
Save AlexandrHoroshih/231b6c22608e1e1baafa1f8c69a4ab02 to your computer and use it in GitHub Desktop.
effector + history
import { matchPath, RouteProps } from "react-router";
// historyUpdated event is subscribed to history via history.listen or any other way
export const createPathMatcher = <Match = unknown>(config: {
path: string | string[] | RouteProps;
clock?: Event<any> | Store<any> | Effect<any, any>;
}) => {
return sample({
source: historyUpdated,
clock: config.clock ?? historyUpdated,
fn: (update) => {
const { location } = update;
return location ? matchPath<Match>(location.pathname, config.path) : null;
},
}).filterMap((match) => (match ? match : undefined));
};
// usage
const formMatched = createPathMatcher<{ id: string }>({
path: "/form/edit/:id"
});
// formMatched has { params: { id: string }, // + match meta fields } payload
// formMatched will be called only if matchPath returned match object (it can also return null, if no match)
// usage with route props
const homeMatched = createPathMatcher({
path: {
path: "/home",
exact: true
}
});
@AlexandrHoroshih
Copy link
Author

matchPath as effect

export const createPathMatcher = <Match = unknown>(config: {
  path: string | string[] | RouteProps;
  clock?: Event<any> | Store<any> | Effect<any, any>;
}) => {
  const matchPathFx = createEffect((update) => {
      const { location } = update;

      return location ? matchPath<Match>(location.pathname, config.path) : null;
  })

  sample({
    source: historyUpdated,
    clock: config.clock ?? historyUpdated,
    target: matchPathFx
  })
  
  return guard({
    clock: matchPathFx.doneData,
    filter: Boolean
  })
};

// usage
const formMatched = createPathMatcher<{ id: string }>({
  path: "/form/edit/:id"
});


// formMatched has { params: { id: string }, // + match meta fields } payload
// formMatched will be called only if matchPath returned match object (it can also return null, if no match)

// usage with route props
const homeMatched = createPathMatcher({
  path: {
   path: "/home",
   exact: true
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment