larrymyers / react-mini-router Goto Github PK
View Code? Open in Web Editor NEWA minimal URL router for React.js
License: MIT License
A minimal URL router for React.js
License: MIT License
If I get a url like http://www.exmaple.com/home#!/message?=c=c&d=d., and I share it to the wechat app, the app will auto add params to the url like http://www.exmaple.com/home?a=a&b=b#!/message?=c=c&d=d.
I will get the params as : {c:'c', d: 'd?a', b: 'b'}, and the process will catch a error.
I resovle this question with:
function getInitialPath(component) {
var path = component.props.path || component.context.path,
hash,
url;
if (!path && detect.canUseDOM) {
url = urllite(window.location.href);
if (component.props.history) {
path = url.pathname + url.search;
} else if (url.hash) {
hash = urllite(url.hash.slice(2));
path = hash.pathname + hash.search;
if(window.location.search) {
path = hash.pathname + hash.search + window.location.search.replace('?', '&');
} else {
}
}
}
return path || '/';
}
function getInitialPath(component) {
var path = component.props.path || component.context.path,
hash,
url;
if (!path && detect.canUseDOM) {
url = urllite(window.location.href);
if (component.props.history) {
path = url.pathname + url.search;
} else if (url.hash) {
hash = urllite(url.hash.slice(2));
path = hash.pathname + hash.search;
if(window.location.search) {
path = hash.pathname + hash.search + window.location.search.replace('?', '&');
} else {
}
}
}
return path || '/';
}
It seems that you are unable to use this.setState or this.props.whatever within the route callback functions. I'm trying to set some states based on the route that is selected but nothing is working.
routes: {
"/": "index"
}
index: function() {
this.setState({ myState: 'cool' });
return <MyComponent />
}
Uncaught Error: Invariant Violation: replaceState(...): Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.
If i try setting a prop it seems the props I set do not become available within the render function. I also tried using Fluxxor and setting the state via an action to a Store and then using StoreWatchMixin to update the state. But this doesn't work either because StoreWatchMixin checks this.isMounted() before updating the state...but this.isMounted() is false thus no state update occurs.
I'm using a payment gateway that sends normal POST data to the clients browser, how do I access the POST data before rendering?
The npm package version needs to be bumped to get the React 15.4.0 compat patch into the registry.
Will this module be compatible with React 16?
Currently not matching a route on navigation is a no-op. Should be allowed to define a 404 route.
This is not an issue but really just a question. Firstly, I want to say that i love the simplicity behind react-min-router.. it is working very well for me..
So, I have render method written like so to include wrap the current wrap into a header /footer:
render : function () {
return (
<div className="container">
<div className="page-header">
<h1>Header</h1>
<a href="/">default page</a> | <a href="/section/page1">page 1</a>
</div>
{this.renderCurrentRoute()}
<div className="footerWrapper">
<h2>This is a footer</h2>
</div>
</div>
);
}
Now, i want to have a route (login) that should just render itself and nothing else. (The login page should show only login form. i.e. no standard layout.)
Can you tell me how i would best accomplish this?
I'm in the process of writing an app that needs to respond to manual changes in the url - which it does currently. However that response is almost always going to involve a change in state (and a async backend call).
Simplified example:
mixins: [Reflux.connect(Store, 'store'), MiniRouter.RouterMixin],
routes: {
'/': 'home',
'/:tt_id': 'tt',
'/:tt_id/:term_id': 'term'
},
I've inserted calls to the store in appropriate places when the user is navigating within the app and that works fine. However my issue comes up with the user is on say /2/2 and then manually changes to /2/1. The render component for the navigation fires however I can't update state there otherwise it obviously causes a render loop. Since the component is already rendered getInitialState won't work. Is there another place you can suggest putting this call?
Hi Larry,
Just testing with IE8 and the links are not working for me. The routing in general seems to be fine but when I click a normal link, it just goes to the /url without the hashbang (works fine in Chrome of course). Any ideas why this is happening?
From a quick look getHref function does not seem to return a URL in IE8 but I might be looking at the wrong thing.
Many thanks,
I've got a situation where I have to use navigate to the same route but with different parameters. My route is set up as:
var App = React.createClass({
mixins: [RouterMixin],
routes: {
'/preview/:id': 'previewPage',
...
}
...
});
I'm starting at the route /preview/123456
and then using the navigate command to navigate to /preview/789012
:
var React = require('react'),
Navigate = require('react-mini-router').navigate;
var PreviewPage = React.createClass({
...
changeProduct: function(productId) {
Navigate('/preview/' + productId);
},
....
});
I'm able to see the URL change, however it seems like since I never changed the route and only changed the route parameters, the view never refreshes. I found a work-around where I update the state variable that holds the product information as part of the changeProduct
function, but shouldn't Navigate() update the page regardless of the route changing or not?
Thanks!
A link in the component is ok, but when we hit a back button, the link does not work anymore. Is this a known issue?
Hi,
I was wondering if some methods could be added to your lib:
Maybe its best to keep the lib light and add those method in a separate object, I'd like your opinion, I could make a PR later.
Right now the RouterMixin claims 'path', 'root', and 'useHistory'. These should be namespaced in the state object to free up these variable names.
Use React's invariant function to validate the state variable for RouterMixin isn't stomped on.
I'd like to be able to define a custom root path that all routes will be resolved against. So if my component was initiated with App({ history: true, root: "/dev" })
/
matched /dev/
/foo
matched /dev/foo
This way you can run the application from a sub directory like /v2
or /beta
by only changing one configuration option.
webpack recommends using the CommonJS-version of a library if possible (webpack/webpack#299), and since the published packages in npm
and bower
only have the distributed and minified files, webpack is not happy.
Including index.js
and lib
would resolve this issue.
Hi,
After upgrading to React 0.14 I get the following error message:
ERROR in .//react-mini-router/lib/RouterMixin.js/react-mini-router/lib/RouterMixin.js 2:20-54
Module not found: Error: Cannot resolve module 'react/lib/EventListener' in /path/to/project/node_modules/react-mini-router/lib
@ ./
I have an isomorphic React app and I'm using react-mini-router in an independent app that is meant for client side only rendering. The problem is that apparently react-mini-router isn't aware on server side that it is being used like this and thus it always renders the index page server side, thus leading to Invariant Violation because client renders different path.
My current solution to this problem is uglyish:
getInitialState: function() {
return { clientRenderingIsSafeNow: false }
},
componentDidMount: function() {
this.setState({ clientRenderingIsSafeNow: true })
},
render: function() {
// server side doesn't know our hash path so we render wrong stuff in client and get Invariant Violation
// so we render empty div in both server and client until componentDidMount, which happens only in client
if (!this.state.clientRenderingIsSafeNow) {
return <div />
}
return this.renderCurrentRoute()
},
Is there a better way?
When I use navigate() to change url, if the path didn't change, the page won't change.
Is this bug?
We used to have an a tag like fusrcreate.html?id=0, how would we pass the id as part of a link?
Thanks!
I'm adding React Router for server side rendering, while I have React Mini Router for hashbang usage within a non-indexable client-only app. The issue is that React Router passes history object internally to every component it renders. React Mini Router uses this value to go itself to non-hash mode, which means when React Router renders the component React Mini Router will never go into hash mode.
Thus I think the check for history property should be explicit true value; or a more descriptive prop name should be used instead, because history={true}
doesn't really tell what is going to be true; with React Router history prop is more understandable as you need to create a history object and pass that.
Hi Larry,
Thanks for react-mini-router. I'm quite new to JavaScript, React and react-mini-router, so I apologize beforehand for asking for the obvious or being rather clumsy in my explanations :)
It seems that react-mini-router renders all my routes twice, each time I click one of my menu links. Can you give me any clues why that might happen and how it can be avoided?
Regards,
Pieter-Jan de Vries
The company I work for is currently developing two applications, one that is using mini router ^1.7.0
and a new one that is using ^2.0.0
.
With the 1.7.0 app, we are not using push state, and set our routes like:
routes: {
'/': 'renderRoot',
'/items': 'renderItems',
'/items/:id': 'renderItem'
}
This works as expected, but in our new ^2.0.0
based app, it does not.
The new application is a static application that launches from app.html
, so our router properties look like this:
ReactDOM.render(
<AppRouter root='/app.html' />,
document.getElementById('app')
)
We have wrapped our render like this:
render: function () {
return (
<div>
{ this.renderCurrentRoute() }
</div>
)
}
But when we specify a url in a link, the router does not catch it and removes app.html#!
from our url, which breaks our application. Furthermore, we added a notFound: function (path) {}
method, which detects all of our urls to be wrong if the defined route starts with a backslash.
We did not have this behaviour in ^1.7.0
and were wondering if there was some sort of regression, or if this is a feature that isn't documented properly.
Thanks for any help.
I know that when you configure the router component you can pass a root: "/some/app/root"
value. This is excellent. However, navigate()
doesn't seem to respect this root value. Would this be something you'd consider adding?
// App
{
routes: {
"/": "home",
"/account": "account"
}
}
App({root: "/myapp" }) // /myapp is home
navigate("/account")
// should be /myapp/account
// instead is /account
RC1 is out. See if anything breaks and determine the next version number.
any plans?
I have an flux app where I would like to call state altering action when certain route is "requested". Is there a place to do this outside of render method? Something like onNavigate.
Thank you!
ERROR in ./~/react-mini-router/lib/RouterMixin.js
Module not found: Error: Cannot resolve module 'react/lib/getEventTarget
The router is using private APIs that seem to have changed.
Hi Larry,
I didn't solve my multiple route rendering problem yet, but I did run into another problem. In the componentWillMount() method of my main component, I check a user's authentication state and adjust the route accordingly. If the route needs to be changed, I use react-mini-router's navigate() to make it happen. This seems to work as expected, except for the very first page when useHistory is set to false and the url does not contain a #! yet (server default page). In that case detect.hasHashBang() returns false.
I solved this behavior by moving the window.location.hash setting from react-min-router's componentDidMount() to it's componentWillMount(). Do you thank that's an appropriate solution?
Regards,
Pieter-Jan
Hi. By first line and update time, react-mini-router.js and react-mini-router.min.js look like different versions. First one is 1.2.0, second one is 2.0.0
i.e. <div id="chapter4"><a href="#chapter4">chapter4</a>
The current example app needs to be rejiggered to include a nested router.
Verify that nested routes with a notFound route render correctly.
Also verify that if a nested router does not have a notFound route, and the root router does, nested not found errors are caught by the parent router.
Does this router support nested routing? For example I have my root App with it's own routes. Then I go to a Settings App that is linked to from the root App but the Settings App has it's own RouterMixin with it's own routes defined within it for /add, /edit etc. Or does everything have to be defined at the root level only?
Move logic in RouterMixin.js lines 63-72 up into getInitialState. This will ensure path is always set when the component is created.
First off great work on this small neat library, was exactly what I was looking for.
The only issue I had was that the routing fails if the initial path doesn't contain a hashbang,
because navigate
uses detect
to check whether the path contains a hashbang if it doesn't it uses popstate.
I resolved this by verifying the hashbang, e.g.:
function verifyHashbang() {
if (window.location.hash.indexOf('#!') !== 0) {
window.location.hash = '#!/'; // maybe append is better?
}
}
This could be easily done in the RouterMixin
's componentDidMount
if useHistory
is false.
Or did I miss something and am not using the router correctly?
Is there a pre route method to hook into? I would like to check if some form content on a page "is dirty/not saved" and alert the user if they click the browser back/forward button.
Update React to 0.12 release. Mostly changes to example app.
(Currently waiting on grunt-react to update to newer version of react-tools.)
Thanks for this library! It's working well for me, except...
handleClick
is assigned as an event listener to the DOM node in componentDidMount
. However, if you navigate to another 'page' in your Single Page App, and then go back to your previous 'page', componentDidMount
doesn't fire again for that first page, and the original event listener is lost? (That's what happens for me anyway - testing with Chrome v39). This means that when you now click another link on that first page, it won't be caught - it will result in a full page request.
How about also adding the event listener in componentDidUpdate? I tried it and it fixed the problem for me. (I was worried it might keep adding more and more event listeners, but it looks like addEventListener shouldn't allow duplicates*).
If this sounds good, it's just a case of adding:
componentDidUpdate: function() {
this.getDOMNode().addEventListener('click', this.handleClick, false);
},
(I could issue a pull request if you like).
*Or an extra cautious way could be to do removeEventListener
just before the addEventListener
?
I've created a project that aims to be to Routers what TodoMVC is to MV* frameworks by offering the same SPA built in React using different Routers. For it to be successful I need the help of Router writers like you. Will you take the Router Challenge and implement the SPA using your React Mini Router, please?
A RouterComponent can be created that wraps the provided Component. The provided routes can be wired to to the Component by doing a setState({ path: path }) on successful routing changes.
http://facebook.github.io/react/docs/reusable-components.html#es6-classes
Example:
https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
It seems, because of the project's simplicity, this is not possible, but I'm asking anyway as I'm a newbie :)
My idea is to prohibit access to some routes given criteria (such as unauthenticated user). I'm currently using navigate()
inside the routes, but it yields errors as it changes the state during the rendering call...
It seems that there is a weird conflict between react-mini-router and the popuar react-bootstrap, for the full problem please see here.
To replicate the problem you can go to here (source). Pressing the dropdown when you are on the about page, the app navigates back to home.
I have tried to debug the RouterMixin but with little success. Do you have any ideas? Thanks
I have Ubuntu 14.04 with node version v0.10.37. Here is what I get when I run 'npm install':
pavle@pavle-Lenovo-B50-70:~/Desktop/react-mini-router-1.1.6/example$ npm start
> [email protected] start /home/pavle/Desktop/react-mini-router-1.1.6/example
> node server.js
module.js:340
throw err;
^
Error: Cannot find module './app/components/app'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/home/pavle/Desktop/react-mini-router-1.1.6/example/server.js:15:31)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
npm ERR! [email protected] start: `node server.js`
npm ERR! Exit status 8
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is most likely a problem with the react-mini-router-example package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node server.js
npm ERR! You can get their info via:
npm ERR! npm owner ls react-mini-router-example
npm ERR! There is likely additional logging output above.
npm ERR! System Linux 3.16.0-41-generic
npm ERR! command "/usr/bin/node" "/usr/bin/npm" "start"
npm ERR! cwd /home/pavle/Desktop/react-mini-router-1.1.6/example
npm ERR! node -v v0.10.37
npm ERR! npm -v 1.4.28
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/pavle/Desktop/react-mini-router-1.1.6/example/npm-debug.log
npm ERR! not ok code 0
Here is the npm debug log:
0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'start' ]
2 info using [email protected]
3 info using [email protected]
4 verbose node symlink /usr/bin/node
5 verbose run-script [ 'prestart', 'start', 'poststart' ]
6 info prestart [email protected]
7 info start [email protected]
8 verbose unsafe-perm in lifecycle true
9 info [email protected] Failed to exec start script
10 error [email protected] start: `node server.js`
10 error Exit status 8
11 error Failed at the [email protected] start script.
11 error This is most likely a problem with the react-mini-router-example package,
11 error not with npm itself.
11 error Tell the author that this fails on your system:
11 error node server.js
11 error You can get their info via:
11 error npm owner ls react-mini-router-example
11 error There is likely additional logging output above.
12 error System Linux 3.16.0-41-generic
13 error command "/usr/bin/node" "/usr/bin/npm" "start"
14 error cwd /home/pavle/Desktop/react-mini-router-1.1.6/example
15 error node -v v0.10.37
16 error npm -v 1.4.28
17 error code ELIFECYCLE
18 verbose exit [ 1, true ]
Please advise. Thanks.
Pavle
I'm not sure if this is something that can be captured easily (maybe hook on window.unload?), but if I am not using history (history: false
on router component), and right click on a link and open it in a new tab, the router isn't or can't intercept that url change to use a hash-bang, which breaks my widget (it's a widget that embeds into wordpress), and forces the user into a page not found url.
I'm not sure if there is a real and common issue that is fixable in all situations, so should I be implementing the fix in my application, or is there a more generic fix that can be applied to the router?
Edit: I just realized that some of my problem isn't correct, or even track-able. New tab obviously doesn't emit a window.unload, and if the user does a right-click, we lose dom events, so we couldn't even do something like a window.open
I'm getting a Uncaught TypeError: Cannot read property '_currentElement' of null error on my system when I'm just using your example code without any edits. The React.createClass() doesn't cause the error. But the:
React.render(
,
document.getElementById('reactMain')
);
causes the error before the render() function in App is actually called. My version of React is React v0.13.2. Please advise. Thanks.
Don
I am looking to make a link that has an href, but that href is ignored via a preventDefault
, e.g.
<a href="/account" onClick={this.visitAccount}>My Account</a>
This is generally for users / SEO to know where a link will navigate to. However, the visitAccount()
function can perform some logic and possibly decide not to navigate to /account
for one reason or another. Currently, it's not possible to prevent this navigation in react-mini-router.
I know this sounds like an esoteric use case, but part of JavaScript is the ability to control exact user flows, and I am currently being blocked by not being able to preventDefault
on a navigation via react's onClick()
handler for react-mini-router.
I wanted to see if anyone had some insights on how to have an <a>
element that can prevent the default navigation behavior or react-mini-router. I am currently solving this by adding a fork that checks for a stopNavigation
property on the evt
object after the setTimeout()
in handleClick()
but this may not be the rest solution. I would be happy to check for defaultPrevented
but this is always called by handleClick()
Happy for any feedback / to drop a pull request for my patch.
I get and error in ie11.
I found that you use new Event()
which not support in ie in line 315(version 1.1.5).
How can I fix it?
react-mini-router is still used enough that it needs more attention than I can give it on a regular basis. If anybody would be interested in doing issue triage, reviewing pull requests, and fixing bugs I will add them as a maintainer for the project.
The mini-router does not seem to support IE8 out of the box. However It looks at least it loads without errors if you catch addEventListeners using this method but still the links do not redirect, possibly because of hashes in the URL. Has anyone had any success using this with IE8 or any tips? Thanks
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.