ctrlplusb / react-universally

A starter kit for universal react applications.
MIT License
1.7k stars 244 forks source link

404 Errors #456

Closed babysteps closed 6 years ago

babysteps commented 7 years ago

I see that when the Error404 Component is returned server side as a route component, that the status is 404. However, when using react-jobs inside of a route, if there is an error and I render the Error404 component there, it does not return 404 status. How do you handle 404 errors as a result of data not being available?

Not exactly sure how to do it, but it would be great if anytime the Error404 component was returned (anywhere in the tree) that a status of 404 was returned on server render.

Please let me know your thoughts. Thanks!

birkir commented 7 years ago

Hey @babysteps.

If a route wants to flag it self as missed on the server, it needs to set the flag via staticContext prop, which is passed by default with the <Route /> component.

If you simply do a return <Error404 />, the component wont get the staticContext property that it needs.

You can try this:

import { withRouter } from 'react-router';

withRouter(({ staticContext }) => 
  withJob({
    work: () => (<Error404 staticContext={staticContext} />),
  }),
)

edit:

Maybe it works also to return <Route component={Error404} />. Havent tried.

babysteps commented 7 years ago

Thanks @birkir.

I tried the above but am getting an error only when the error component is returned...

export default withRouter(({ staticContext }) =>
  withJob({
    work: () => {
      return ...
    },
    LoadingComponent: () => <div> ...</div>,
    ErrorComponent: props => <NotFound {...props} staticContext={staticContext} />,
  }),
)(MyComponent);

Here is the error in the log:

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. ==> SERVER -> Error in server execution, check the console for more info. Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of AsyncComponent. in AsyncComponent (created by Route) in Route (at index.js:52) in Switch (at index.js:49) in div (at index.js:48) in div (at index.js:42) in App (created by WithJob(App)) in WithJob(App) (at index.js:54) in Router (created by StaticRouter) in StaticRouter (at index.js:53) in JobProvider (at index.js:52) in AsyncComponentProvider (at index.js:51) ==> SERVER -> Error in server execution, check the console for more info. (node:20631) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of AsyncComponent. ==> SERVER -> Error in server execution, check the console for more info. (node:20631) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

birkir commented 7 years ago

Whoops, I think the withRouter behaves differently than I wrote here.

What about this:

export default withRouter(
  withJob({
    work: () => {
      return ...
    },
    LoadingComponent: () => <div> ...</div>,
    ErrorComponent: props => <NotFound {...props} />,
  }),
)(MyComponent));
babysteps commented 7 years ago

hmm... with that i get a build error.

export default withRouter(
  withJob({
    work: () => {
      return ...
    },
    LoadingComponent: () => <div> ...</div>,
    ErrorComponent: props => <NotFound {...props} />,
  }),
)(MyComponent);

I removed the last parathesis (MyComponent)); to (MyComponent); and then it builds, but i still get the following error when the ErrorComponent is returned.

Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead. Server listening on port 5000 ==> SERVER -> Error in server execution, check the console for more info. Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. ==> SERVER -> Error in server execution, check the console for more info. Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of AsyncComponent. in AsyncComponent (created by Route) in Route (at index.js:52) in Switch (at index.js:49) in div (at index.js:48) in div (at index.js:42) in App (created by WithJob(App)) in WithJob(App) (at index.js:54) in Router (created by StaticRouter) in StaticRouter (at index.js:53) in JobProvider (at index.js:52) in AsyncComponentProvider (at index.js:51) ==> SERVER -> Error in server execution, check the console for more info. (node:20890) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of AsyncComponent. ==> SERVER -> Error in server execution, check the console for more info. (node:20890) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

birkir commented 7 years ago

Yeah sorry, I´m writing pseudo code here, Im gonna need full project to get the context. I will try this out later myself.

Are you sure, you´r reference to a valid react component <NotFound />?

babysteps commented 7 years ago

Thanks @birkir. I am sure that NotFound is a valid component (it is basically just the Error404 component from the kit with a few display mods). It works when i don't have the withRouter() wrapper.

P.S. don't know if you remember, but we worked together briefly on RBTV. I did the player :)

babysteps commented 7 years ago

@birkir did you ever get a chance to look at this? I really appreciate your help.

babysteps commented 7 years ago

followup, i found that the issue is w/ react-jobs. it does not server render the ErrorComponent, so the 404 status doesn't work. See issue here: https://github.com/ctrlplusb/react-jobs/issues/34

ctrlplusb commented 6 years ago

The new version will do server rendering of error components 👍