Reputation: 2140
I have the route /messages/:id
that renders a message. However if id
is pointing to a non-existing message, where and how should that be handled? My component is bound to the message using redux:
function mapStateToProps(state, ownProps) {
return {
message: state.messages[ownProps.params.id]
}
}
Then message
will be undefined
in case no such message exist and the component must handle that, and render something different.
However, this seems to bloat the component and I think maybe this should be handled in the router? If there is no such message, it should not allow the route to be called.
Any thoughts?
Upvotes: 7
Views: 2185
Reputation: 4163
I had the same problem, but my final thoughts on this are, that it is not the concern of the router or a getComponent Wrapper, but only the concern of the Component itself to handle it's own (faulty) state.
When your Component is able to be mounted in an erroneous state, like message = undefined, then your Component should react according to the erroneous state.
Preventing your Component from the erroneous state would be an alternative too, but this bloats your code anyways and the Component would still not be able to handle it's error state.
Upvotes: 1
Reputation: 11668
I too am interested in this too and I have a solution, though not the most elegant one. Hopefully this will help though.
import NotFound from './NotFound'
import Message from './Message'
import {asyncGetMessage} from './api'
const onEnter = ({params, location}, replaceState, callback) => {
asyncGetMessage(params.messageId)
.then((isFound) => {
location.isFound = isFound
callback()
})
}
const getComponent = (Component) => {
return (location, callback) => {
callback(null, (state) => {
if (location.isFound) {
state.route.status = 200
return <Component {...state} />
} else {
state.route.status = 404
return <NotFound {...state} />
}
})
}
}
const routes = (
<Route path='messages'>
<Route path=':messageId' getComponent={getComponent(Message)} onEnter={onEnter} />
</Route>
)
What is happening here is the onEnter
method is called initially and waits for the callback. The onEnter
calls the asyncGetMessage
promise and sets the isFound
property on the location
to true
or false
.
Then getComponent
is called, I used a factory to provide the Message
component as Component
. It needs to return a callback, and within the callback, error
and a function with state
as the first argument. From there it checks the isFound
property on location
and returns either the Component
setup in the factory or the NotFound
component.
I am also setting the the route status
to 404 so the server can provide the correct http code when it is rendering the first page load.
Unfortunately the signature of getComponent
doesn't receive state, otherwise it would be possible to do it all there instead of using onEnter
too.
Hope this helps.
Upvotes: 1