4catalyzer / found Goto Github PK
View Code? Open in Web Editor NEWExtensible route-based routing for React applications
Home Page: https://4catalyzer.github.io/found/
License: MIT License
Extensible route-based routing for React applications
Home Page: https://4catalyzer.github.io/found/
License: MIT License
what is the equivalent of react-router-bootstrap LinkContainer for found?
I started this issue a week ago knex/knex#2121 thinking it was an issue with Knex but I've experimented doing the same code with react-router-4 and its working perfectly.
Found: Falieson/planetx-react-postgres@f9d9a31#commitcomment-22539375
ReactRouter: Falieson/simple-react-express@6771400
๐
React Router has a example to show its dynamic routing capability at https://reacttraining.com/react-router/web/example/recursive-paths. How could I implement it using found?
To do this, we'd need to consume the iterable from resolveElements
to the end, then render with that result. We'd have to do the same thing on the client side to set initialRenderArgs
due to the async nature of element resolution as well.
Hi there! I was checking out Found for use on a project that I'm about to work on. While playing with it, I tried doing this:
const routeConfig = [
{
path: 'admin',
Component: App,
children: [
{
path: 'promotions',
Component: () => <div>promos</div>,
children: [
{
path: ':id/edit',
Component: () => <div>here</div>,
}
]
},
]
}
]
The route changes, but the component does not. If I change the nested :id/edit
path to path: 'promotions/:id/edit'
I get the following error:
invariant.js?4599:44 Uncaught (in promise) Error: Objects are not valid as a React child (found: object with keys {status, data}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons.
However, it does work if I do:
const routeConfig = [
{
path: 'admin',
Component: App,
children: [
{
path: 'promotions',
Component: () => <div>promos</div>
},
{
path: 'promotions/:id/edit',
Component: () => <div>here</div>,
}
]
}
]
After looking through the examples, I was under the impression that a child route could have children i.e., https://github.com/4Catalyzer/found#basic-usage
Am I using this incorrectly? Or is it because I'm setting the root path to admin
instead of /
?
Getting this error when there is no initialized state.
Uncaught TypeError: Cannot read property 'match' of null
at Function.ConnectedRouter.onResolveMatch [as mapToProps] (VM3912 bundle.js:32294)
at mapToPropsProxy (VM3912 bundle.js:30183)
at impureFinalPropsSelector (VM3912 bundle.js:64419)
at Object.runComponentSelector [as run] (VM3912 bundle.js:29477)
at Connect.componentWillReceiveProps (VM3912 bundle.js:29601)
at VM3912 bundle.js:59095
at measureLifeCyclePerf (VM3912 bundle.js:58560)
at ReactCompositeComponentWrapper.updateComponent (VM3912 bundle.js:59094)
at ReactCompositeComponentWrapper.receiveComponent (VM3912 bundle.js:59031)
at Object.receiveComponent (VM3912 bundle.js:7878)
Maybe not attempt to resolve a match in this case?
var ConnectedRouter = (0, _reactRedux.connect)(function (state) {
var _getFound = getFound(state),
match = _getFound.match, <--- match is null here
resolvedMatch = _getFound.resolvedMatch;
return { match: match, resolvedMatch: resolvedMatch };
}, {
onResolveMatch: resolveMatch
}, null, {
// Don't block context propagation from above. The router should seldom
// be unnecessarily rerendering anyway.
pure: false
})((0, _createBaseRouter2.default)(options));
Hi,
We're using express with found and found-relay. Currently we get a message concerning an outdated path-to-regexp lib. The root cause of this issue is that express uses version 0.1.7 while found uses version 1.7.
Warning: Incorrect version of path-to-regexp imported. If this is running from a client bundle, check your bundler settings.
Our webpack seems to bundle the 0.1.7 EVERY TIME. Has somebody encountered this issue already and has a solution to it?
We have already tried to explicitly add [email protected] as a dependency to the project, but this fix does not seem to work 100% of the time
thx
Hey,
Is there a way to update the prepareVariables for re-render Component with new params ?
RedirectException
should be imported from found
instead of found/lib/server
in Server-side rendering with custom Redux store example
Hi, below Link
always use PUSH
regardless of action
. Is this behavior correct?
<Link
to={{
action: 'REPLACE',
pathname: '/home',
}}
>
I set up Found using the createConnectedRouter
way. When I dispatch push
or replace
actions from Farce, I see that they're dispatched, but the reducer state doesn't change and as a result I'm not redirected to the target location.
Is there anything obvious that I missed in the config? Basically I need a way to redirect the user from within my action creators.
Hi, I'm having a hard time trying to make webpack + react hot reloading when using this router.
My current setup:
Hot reloading is working until I try to use the router. I think it's related to the routes being defined in the redux store middleware -> createMatchEnhancer -> matcher.
Could you please provide some guidelines or an example on how to achieve this?
thanks!
Is Found used by anyone in production?
I didn't find any mention of React Native in documentation or issues. Is it supported?
Found relay is working great on web and it would be great to use it on mobile as well.
Thanks!
Firstly, this looks like a amazing library, so thanks for all your hard work !!!
We are currently using mobx and are looking to use this router, however I we would prefer not to take a dependency on redux.
Is there a reason this library takes a dependency on redux rather than providing redux support as a seperate package. For example react-router
and react-router-redux
?
I really like the design of found to load data and component in parallel. However, there is a nice thing about data dependency colocated with component. Now, I'm wondering if there is a found way to colocate the data dependencies in component when doing code splitting?
Specific code from docs to illustrate the question.
<Route
path="/"
Component={AppPage}
>
<Route
Component={MainPage}
/>
<Route
path="widgets"
>
<Route
Component={WidgetsPage}
getData={fetchWidgets}
/>
<Route
path="widgets/:widgetId"
getComponent={() => (
System.import('./WidgetPage').then(module => module.default)
)}
getData={({ params: { widgetId } }) => ( /* <------------------------- getData here
fetchWidget(widgetId).catch(() => { throw new HttpError(404); })
)}
From the sample code above, getData function can not be inside WidgetPage if you don't want waterfall. In other words, how does found-relay solve this?
Hi,
the situation is, that I need to use fetch (or similar) to get JSON data from api in getData method on component. When I enter the page (or after hard refresh), everything works as expected, all actions are fired properly, store is updated.
But I encounter problems once I change something in my code and my HMR starts to replace modules. First of all, you can notice that the action is being triggered twice, that does not seems correct. This behaviour also appears in este, which my stack is heavily based upon (thx Daniel if u r reading this :) ).
In contradiction to este, I'm not using firebase, and where "queryFirebase.js" sits I'm simply calling action I choose. Error I'm getting is "net::ERR_CONNECTION_REFUSED", when I inspect headers of the request it's basically empty, there is no method, no status code, seems like the request is getting canceled or something. Also there is redux-promise-middleware in the middle.
<Route
Component={MyPage}
getData={pageRequest(getServerData)}
/>
const pageRequest = (action) => (
({ context: { store } }) => store.dispatch(({ ...deps }) => action(deps))
)
const getServerData = ({ fetch }): Action => ({
type: 'GET_DATA',
payload: fetch('http://localhost:3000/api/v1/data')
.then(response => response.json())
.catch(e => console.log('Fetching failed', e)),
})
I'm rather lost, thanks for any help. If you need more info I will provide as much as I can.
I'm guessing the solution for both these problems centers around a correct .babelrc in the universal-redux folder
$ git clone 4Catalyzer/found
$ cd found/examples/universal-redux
$ npm install
$ npm start
$ babel-node src/server
/Users/florian.mettetal/Code/.private/found/examples/universal-redux/node_modules/babel-core/lib/transformation/file/options/option-manager.js:180
throw new ReferenceError(messages.get("pluginUnknown", plugin, loc, i, dirname));
^
ReferenceError: Unknown plugin "dev-expression" specified in "/Users/florian.mettetal/Code/.private/found/.babelrc" at 0, attempted to resolve relative to "/Users/florian.mettetal/Code/.private/found"
at /Users/florian.mettetal/Code/.private/found/examples/universal-redux/node_modules/babel-core/lib/transformation/file/options/option-manager.js:180:17
at Array.map (native)
at Function.normalisePlugins (/Users/florian.mettetal/Code/.private/found/examples/universal-redux/node_modules/babel-core/lib/transformation/file/options/option-manager.js:158:20)
at OptionManager.mergeOptions (/Users/florian.mettetal/Code/.private/found/examples/universal-redux/node_modules/babel-core/lib/transformation/file/options/option-manager.js:234:36)
at OptionManager.init (/Users/florian.mettetal/Code/.private/found/examples/universal-redux/node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
at compile (/Users/florian.mettetal/Code/.private/found/examples/universal-redux/node_modules/babel-register/lib/node.js:103:45)
at loader (/Users/florian.mettetal/Code/.private/found/examples/universal-redux/node_modules/babel-register/lib/node.js:144:14)
at Object.require.extensions.(anonymous function) [as .js] (/Users/florian.mettetal/Code/.private/found/examples/universal-redux/node_modules/babel-register/lib/node.js:154:7)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
error Command failed with exit code 1.
$ git clone 4Catalyzer/found
$ cd found/
$ rm .babelrc
$ cd examples/universal-redux
$ npm install
$ npm start
$ babel-node src/server
SyntaxError: /Users/florian.mettetal/Code/.private/ultimate-react/src/server.js: Unexpected token (86:6)
84 | .status(renderArgs.error ? renderArgs.error.status : 200)
85 | .send(renderPageToString(
> 86 | <Provider store={store}>
| ^
87 | <RouterProvider router={renderArgs.router}>
88 | {render(renderArgs)}
89 | </RouterProvider>
at Parser.pp$5.raise (/Users/florian.mettetal/Code/.private/ultimate-react/node_modules/babylon/lib/index.js:4454:13)
Almost always this will be a typo for Component
.
Or maybe we should just support it. I dunno.
React-router provides a way to provide multiple components for a single route. It would be nice if found would match this functionality.
I am using the este.js stack and redux-observable middleware epics to make my API calls and trigger other actions when needed. But the server-side rendering is not waiting for the final result to render the app.
Do you have any idea on how I can make this work?
<Route>
<Route
path="/"
Component={App}
getData={({ params, context }) =>
context.store.dispatch({
type: 'GET_TIMEZONES',
})}
render={({ Component, props }) => {
if (!Component || !props) {
return 'Loading';
}
return <Component {...props} />;
}}
>
</Route>
export const setTimezonesEpic = (action$: any, { getState }: Deps) =>
action$
.filter((action: Action) => action.type === 'GET_TIMEZONES')
.mergeMap(() => {
const baseUrl = getState().config.gatewayServiceBaseUrl;
const viewer = getState().viewer;
const headers = buildHeaders({ viewer, jsonBody: false });
return Observable.from(
fetch.get({
headers,
url: '/users/api/timezones',
baseUrl,
})
)
.map(timezones => setTimezones(timezones))
.catch(error => Observable.of(getTimezonesFail(error)));
});
I thought Redux was not going to be needed in my React application, but now this need came and it seems Redux state is being replaced by found.
I can be wrong, but running this code:
const mapStateToProps = state => { console.log(state); return { sidebar: state.sidebar }; };
I got this output in console:
Object { found: Object }
So I can't get the sidebar piece of state. My rootReducer is defined as:
const rootReducer = combineReducers({ sidebar: Sidebar });
Is there anyone who had this same problem?
I want to test my components with Snapshots and am using Jest to do so. Since my component is using withRoute HOC, both my component and somewher in HOC require router
and all its functions in their in the contexts.
Is there a easy way to create an instance of router
or mock it?
Here is a sample of my code:
const initialState = store.getState();
const router = {}; // ???
test('Login changes', () => {
const wrapper = shallow(<Login />, {
context: { store: mockStore(initialState), router }
});
expect(wrapper.dive()).toMatchSnapshot();
});
TypeError: Cannot call a class as a function
at exports.default (/Users/danielsteigerwald/dev/este/node_modules/babel-runtime/helpers/classCallCheck.js:7:11)
It's because docs are suggesting throw HttpError(401);
instead of throw new HttpError(401);
Btw, we can use https://github.com/JsCommunity/make-error for real JavaScript errors.
Hey, great project!
We use react-router@3
at the moment, but not really sure if migrating to @4
is going to happen any time soon, if ever. So, found
looks like a great alternative as soon as some migration instructions from react-router will be available โย I'm sure lots of people will appreciate that. Thanks
I converted my app from react-router v2 to found and it's been great. However, I hacked on a feature a while back and haven't figured out how to sensibly bring that over to found:
For most users, I want to use one set of routes. For a specific type of users, I want to use a much smaller set of routes. With react-router v2, I could just fetch the user (Redux-based) and then branch on what routes to render.
With a Redux-connected found, I'm not seeing a good way to do this. I see these options:
don't create the store so don't use my redux actions/store for the initial user fetch but instead fetch data, then create everything (and can pass fetched data into initial redux store state to avoid duplicate fetch)
use the happy path for most users but for the special-case users, update the Redux enhance createMatchEnhancer
with the smaller route set (sounds potentially buggy)
I'm going to go with the first approach for now to unblock myself but I sense I'm missing something obvious so thus this issue.
Hey I've been researching and trying different things but can't seem to figure out how I could change the root route to be something like /app
instead of just /
. Would I just wrap everything in a <Redirect>
component?
The use case is basically having a new SPA built along side an existing application and we want to have it nested inside the /app
directory and so would like to treat that as the "root" for the SPA.
When I catch an error 401, I wanna redirect to /login.
I used compoent Render
but an error occured: Cannot call a class as a function
So, How to fix it.
`
render: createRender({
renderError({ error }) {
switch (error.status) {
case 404:
return <GenericError />;
case 401:
return <Redirect from="/diary" to="/login" />;
default:
return null;
}
}
})
`
If we getData on the server side and deliver them to the client withing Redux initialState, how we can bypass the initial getData? Manual checking?
Hi! I have recently decided to build a new project and try found instead of RR3, but in my previous project I've always used immutable stores created with redux-immutable.
For a non-immutable.js user it means, that instead of the normal combineReducers, the store is created with a combineReducers from redux-immutable, which creates a Map instead of a normal JS object.
Meaning, that if I would try to use a normal shared-store configuration, it would fail due to inability to access data from an immutable store.
Therefore, my question is - is it possible to make a support for immutable-js users?
It would be really great if you could implement it or at least give me some guidance so I could implement in myself.
Thanks.
Hi Jimmy!
I've been following and using tools you have written/maintained, react-router, react-router-relay and now that I see found. Really like the rationale about found and what it aims to solve. I'm sure there are people like me who never got the chance to say this. So just wanna drop by and say THANK YOU for your work.
About found, please let me know if I could help on anything on your to-do list or roadmap.
I'm using the following scheme for checking for a logged-in user using Found (along with Relay Modern) -
<Route
path="/"
Component={App}
prerender={ ({ props, match }) => {
const login_path = match.location.pathname == "/login";
const logged_in = props && !!props.viewer;
if (login_path && logged_in) {
throw new RedirectException("/");
} else if (!login_path && !logged_in) {
throw new RedirectException("/login");
}
}}
query={graphql`
query routes_Query {
viewer {
...App_viewer
}
}
`}
>
This works fine for the most part, except in my login mutation, when I want to programmatically navigate to the root route upon login success (excerpt from mutation) -
onCompleted: (response) => {
if (response.login.success) {
router.replace("/");
} else {
console.log("Auth failed");
}
},
Issue
When I perform the navigation using this technique, my prerender
handler doesn't receive the new props (specifically in my case, viewer
remains null
). However, if I do a hard page refresh at that point, things function as expected.
Does this sound like a bug? Or am I just doing something fishy
When not using babel as transpiler. Installing the dep fixed it.
// createRoutes.js
import { Page as AppPage } from './index';
import { Page as MainPage } from 'web/mobile/Main';
export const createRoutes = () => {
const routeConfig = [
{
path: '/',
Component: AppPage,
children: [
{
Component: MainPage,
},
],
},
];
return {
routeConfig,
};
};
// main.jsx using routeConfig
...
const ConnectedRouter = createConnectedRouter({
routeConfig,
matcher,
render: createRender({
renderError: ({ error }: { error: any }) => (
<div>
{error.status === 404 ? 'Not found' : 'Error'}
</div>
),
}),
});
const BootstrapComponent = (
<Provider store={ store }>
<ConnectedRouter resolveElements={ resolveElements } />
</Provider>
);
render(
BootstrapComponent,
document.getElementById('__ROOT__')
);
Result:
How would you recommend I create an instance of founds initial state so I can test against a mocked version of the redux found reducer state?
Hey all. Love the library. Great work.
Having an issue with a complex usage of the Redux-connected createConnectedRouter
(although I sense my issue is agnostic of the fact that I'm using that as opposed to the "basic" usage).
My implementation:
function App({ children }) {
return (
<div>
<h1>The App</h1>
{children}
</div>
)
}
function NestedComponent() {
return <div>The nested component</div>
}
function getData() {
return promiseReturningFunction().then((someValue) => { someValue })
}
const routeConfig = makeRouteConfig(
<Route
path='/'
Component={App}
getData={getData}
render={({ Component, data, props }) => {
if (!data) {
return null
}
return <Component {...props} />
}}
>
<Route path='/nested' Component={NestedComponent} />
</Route>
)
const createStoreWithEnhancers = composeEnhancers(
createHistoryEnhancer({
protocol: new BrowserProtocol(),
middlewares: [queryMiddleware],
}),
createMatchEnhancer(new Matcher(routeConfig)),
)(createStore)
const reducer = combineReducers({
found: foundReducer,
})
const store = createStoreWithEnhancers(reducer)
const ConnectedRouter = createConnectedRouter({
render: createRender({}),
})
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter resolver={resolver} />
</Provider>
)
With the code above, I am noticing that on the initial render pass, although the render
for the top-level <Route />
is returning null
(as a result of getData
), the child <Route />
's component (NestedComponent
) is still getting rendered for a brief moment (without the wrapping App
component being rendered). Note that the render lifecycle of App
isn't even being invoked. The NestedComponent
is rendering completely outside of that context. In the second pass that occurs after getData
is resolved, both components render as expected (with NestedComponent
being rendered as a child of App
).
When tracing the unexpected render of NestedComponent
it looks like it's simply coming from the resolveMatch
of the BasicRouter
.
My expectation would be that child <Route />
s and their Component
s do not render if their parent <Route />
's render
is returning null
. Am I perhaps thinking about this the wrong way?
Happy to provide more debugging information if necessary.
Edit
For some added clarification, the visual output is as follows.
getData
is resolved, the page reads (as expected) "The App" followed by "The nested component"I have looked for the ability to set a base url in the various repos, but didn't see it - apologies if I missed it
I run a web app on a child url of the main domain (i.e. www.hello.com/world) so the urls all need to have /world
prepended to them
I was originally using react-router, with router history and did it like this:
const browserHistory = useRouterHistory(createHistory)({ basename: /world });
is this possible yet in Found? I am using the createFarceRouter
I think this is coming from found, apologies if it is not, but very hard to track down.
I get this warning in my console.
Failed propType: Calling PropTypes validators directly is not supported by the `prop-types` package
with this code
ReactDOM.render(
<BrowserRouter resolver={resolver} />,
document.getElementById('root')
);
where BrowserRouter is ...
import { makeRouteConfig, Route } from 'found';
import createFarceRouter from 'found/lib/createFarceRouter';
import queryMiddleware from 'farce/lib/queryMiddleware';
import BrowserProtocol from 'farce/lib/BrowserProtocol';
import createRender from 'found/lib/createRender';
import React from 'react';
import App from './containers/App';
export default createFarceRouter({
historyProtocol: new BrowserProtocol(),
historyMiddlewares: [queryMiddleware],
render: createRender({}),
routeConfig: makeRouteConfig(
<Route path="/" Component={App} />
),
});
I do NOT get it if I render App directly as in ...
ReactDOM.render(
<App />,
document.getElementById('root')
);
Probably going to feel stupid when I find the issue but seems to be related to either found or farce.
On...
"farce": "^0.2.3",
"found": "^0.3.5",
Is there a prop for disabling a Link? I'm not finding one, but maybe did you have another approach in mind for disabling?
I'm not sure how to implement authorised routes. I need to check Redux state.users.viewer to enforce redirect with requested location. Does it belong to routeConfig or it should be a higher order component? Can we use <Redirect />
component in a view?
How can I pass a basename other than '/' to createConnectedRouter
(when using a shared Redux store)?
Is it possible to create the same DX as zeit/next.js on top of the found?
Is it ok to use dispatch like that? I need pending status deeper in the app tree.
export const createRouterRender = (renderArgs: any) => createRender({
renderPending: ({ context: { store: { dispatch } } }) => {
dispatch({ type: 'SHOW_PENDING' });
return (
<div>
<StaticContainer>
{null}
</StaticContainer>
<PendingProgress />
</div>
);
},
renderReady: ({ context: { store: { dispatch } }, elements }) => {
dispatch({ type: 'HIDE_PENDING' });
return (
<div>
<StaticContainer shouldUpdate>
<ElementsRenderer elements={elements} />
</StaticContainer>
</div>
);
},
renderError,
})(renderArgs);
We should have a way to reload routes without re-creating the store from scratch.
Real-time databases like Firebase based on web socket need to dispose of observable data. Can we detect route has been left somehow?
Which is the minimum supported browsers? Same as React?
Relative link navigate to the right url, but it seems that found does not know what route it is supposed to render if the url pushed was relative.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.