I'm loving v4 but in 4.1.2 this keeps tripping me up when using the browser router:
With a component in a Route component I have these props passed in: {computedMatch, location, path} although the documentation tells me to expect {match, location, history} which is what I get with the hash router.
To get the history passed in I have to use the withRouter wrapper which feels very clunky because the relevant component is the component prop to a Route component.
The documentation sounds right to me. Is this a bug?
You can get access to {match, location, history} if you use Route as
<Route path="/" component={myComponent}
In above code you will have match location and history accessible inside myComponent.
Or else you have to use withRouter
Related
I'm using React Router 4. I would like to know how to get the full current path in a matched component, not just the base path.
I know that React Router inject a history and location objects in the props of the rendered component. I've realized that I could either do
props.history.createHref(props.location)
or build the path manually with
props.location.pathname + props.location.search + props.location.hash
Are there better ways to do this?
My use case: application has a header that displays current user's name. This header is the same on all pages.
User data is loaded from JSON API into the Store when user logs in.
Now, how am I supposed to access this data from Store to use it on every page?
One option is to pass it from routes:
{{app-header user=model}}
But then I would have to use the same model in all the routes and also would be unable to use any other? How can a (supposedly reusable) component expect from me to adjust every route to its data structure?
The other option is that component always loads data from Store on its own, but this seems strongly unrecommended and actually very hard to do for me without any proper guide. I managed to discover service injection method (store: Ember.inject.service() in the component) but still can't get the component to properly display data from store in the template.
When I use:
name: () => {
return this.store.peekRecord('user', 1).get('name');
}
then {{name}} in template renders function definition, not what it returns.
When I use:
name: Ember.computed(() => {
return this.store.peekRecord('user', 1).get('name');
})
then {{name}} renders: <!---->
Could you please explain what is a good way to do this? Is there some "master model" defined in application.js besides models from routes? Should I really pass the same data to component in every route? Any information or suggestions will be greatly appreciated.
You could try using a service (guide here).
// app/services/store.js
import DS from 'ember-data';
export default DS.Store.extend({});
// app/services/user-service.js
import Ember from 'ember';
export default Ember.Service.extend({
store: Ember.inject.service(),
user: Ember.computed(function() {
return this.get('store').findRecord('user', ':id');
})
});
Then, in all your other components, controllers, and routes, you can access the service.
// Inside a controller
export default Ember.controller.extend({
userService: Ember.inject.service(),
firstName: Ember.computed.alias('userService.user.firstName')
});
The first name, or even the user object itself is now available in you template.
{{userService.user.firstName}}
OR
{{firstName}}
First approach, (Keeping it in Application Route)
1.Define it in application route model hook - refer multiple modelsin single route.(https://guides.emberjs.com/v2.9.0/routing/specifying-a-routes-model/#toc_multiple-models)
2.If its required in another route, then you can access already resolved model of the parent route through modelFor method.(http://emberjs.com/api/classes/Ember.Route.html#method_modelFor)
Second Approach, (Service)
Like #devman answer, you can load it in service and inject and get it wherever you require.
userService:Ember.inject.service();
name: Ember.computed.alias('userService.name')
I am creating a blog using React/React-Router/Redux, and depending on the location, I want to show different blog posts, so if you are on /category/cat1 you don't have the same list of blogs than if you are on /category/cat2.
So I'm thinking on storing the blog list in the store and my react component would pick it up from there so I could just have actions updating my state.
My thinking is listening on the browserHistory so I can get when the location changes and trigger the action which would update the new blog list, but I can't find how to get the params from my location path like I would from my component props /category/:catName
How can I get those params?
Is it actually the way to do it or should I use a different approach?
Thanks.
From the version 2.0.0 upgrade guide:
RoutingContext -> Router render prop
You can now pass a render prop to Router for it to use for rendering.
This allows you to create "middleware components" that participate in
routing. Its critical for integrations with libraries like Relay,
Redux, Resolver, Transmit, Async Props, etc.
The default is basically this:
<Router render={props => <RouterContext {...props} />} />
This render prop on the Router is a hook into the render stage, and those props that are passed to the function contain the parsed route params, as well as lots of other routing context. Just make sure your function returns a RouterContext, or some equivalent, in the end.
I'm using react-router 1.0.3. Say I define these routes
<Route path="/" component={App} onEnter={appOnEnter}>
<Route path="test" component={Test} onEnter={testOnEnter} />
</Route>
Both appOnEnter and testOnEnter are asynchronous functions. By default testOnEnter waits for appOnEnter to finish and call the callback to run, but I want those 2 onEnter functions to run simultaneously, how can I do that?
This won't work with the react-router 1.0.3. I checked the source-code of it and don't see a way to call both hooks at the same time.
Here is a reference to the onEnter-Hook handling, if you might want to take a deeper look into it: https://github.com/rackt/react-router/blob/v1.0.3/modules/TransitionUtils.js
Maybe you can find a way to trick the system...
But I also would not recommend doing it. I don't have an idea of what you want to achieve but I think you should find a different approach, using other life-cycle hooks that react provides.
Is this outdated? https://github.com/rackt/react-router/blob/95094769caca201b8e9afe68ff3d6cb4ff280fac/docs/advanced/NavigatingOutsideOfComponents.md
I can't seem to get it working.
I'm exporting the history object like this:
export const history = require('history/lib/createBrowserHistory')();
And then I'm using it like so:
history.push('/home');
But the page doesn't change, only the URL changes.
This functionality still works fine and the current docs still have it in master
Notice the extra () at the end of the require in your code. That's a function call which returns a new history object instance.
In that doc they do the function call once in history.js and export the instance. They then require history.js and used that instance for both the router and outside of the router.