Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle invalid ID in react-router route in a redux app?

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?

like image 980
philk Avatar asked Feb 01 '16 10:02

philk


2 Answers

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.

like image 183
Marc Greenstock Avatar answered Oct 24 '22 18:10

Marc Greenstock


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.

like image 31
larrydahooster Avatar answered Oct 24 '22 18:10

larrydahooster