React Router / Hapi Server Side Rendering Error - reactjs

I've been struggling this for a while, and previously had this working, but inexplicably, it's broken again, so clearly the root cause has not been resolved.
React Router v: 2.0.0-rc4
Issue: When loading a page, server returns the following error.
Warning: Failed propType: Required prop `router` was not specified in `RouterContext`.
Warning: Failed propType: Required prop `location` was not specified in `RouterContext`.
Warning: Failed propType: Required prop `routes` was not specified in `RouterContext`.
Warning: Failed propType: Required prop `params` was not specified in `RouterContext`.
Warning: Failed propType: Required prop `components` was not specified in `RouterContext`.
Warning: [react-router] `<RouterContext>` expects a `router` rather than a `history`
The page loads normally though, and client side routing seems to work just fine.
relevant snippet from Server.js:
import routeConfig from './../common/routes/Routes.js';
const handleRender = function(req, res) {
const initialState = {
profile: {
name: 'Bob',
age: 10
},
messages: []
}
const createStoreWithMiddleware = applyMiddleware( thunkMiddleware)(createStore);
const store = createStoreWithMiddleware(reducer(initialState));
match({routes: routeConfig, location: req.url}, (error, redirectLocation, renderProps) => {
// res(req.url);
if(error) {
res('error' + error.message);
}
else {
res(renderProps);
const html = renderToString(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
);
//const initialState = store.getState();
//res(renderFullPage(html, initialState));
}
});
}
Here is what is exported from Routes.js
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import { Route } from 'react-router';
//Components
import App from './../components/App.jsx';
import Name from './../components/Name.jsx';
import Profile from './../components/Profile.jsx';
import Messages from './../components/Messages.jsx';
const routeConfig = [
{
path: '/',
component: App,
childRoutes: [
{path: 'test', component: Name},
{path: 'profile', component: Profile},
{path: 'messages', component: Messages}
]
}
];
export default routeConfig;
When I dump out renderprops, this is what I get
{
routes: [
{
path: "/",
childRoutes: [
{
path: "test"
},
{
path: "profile"
},
{
path: "messages"
}
]
},
{
path: "test"
}
],
params: { },
location: {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: { },
pathname: "/test",
path: "/test",
href: "/test"
},
components: [
null,
null
],
history: {
__v2_compatible__: true
},
router: {
__v2_compatible__: true
}
}
So it seems like it's never matching components. Perhaps I'm passing in req.url incorrectly? But I can't find any react-router documentation that indicates exactly what that argument should look like.

Leaving this here in case anyone else runs into something this silly.
After enabling more robust error logging via Good, I realized that this error was actually in reference to a request to /favicon.ico, which my routes were not handling, and which were falling down into my react routes.
Very dumb mistake on my part, and due to my inexperience with needing to handle/log errors in Hapi.

If you, like me, came here following the reactjs react-router-tutorial on Github (if not, go check it out), these error messages might show because you haven't described any alternatives to finding a route in the Routes'. If it only shows up on undefined routes (try typing something random after localhost:8080/), do yourself a favour and read this to the end.
Also, insert a console.log('req.url: ', req.url) in the app.get call in the server to see what is causing the error.
Also II: Declare appHTML outside of the match function to ensure it survives into res.send().

Related

Webpack keeps saying "Imported module is undefined"

So I have this routes.ts file where I've stored all the routes of my React app that I created with create-react-app. The routes get imported whenever I need to insert some route-related data.
tl;dr Webpack has no issue with a module elsewhere but says it's undefined at one spot.
Here's all the information you need to help me out 🙂
routes.ts
import { Route, PageName } from ".";
...
const routes: Record<PageName, Route> = {
landing: {
PATH: "/landing",
BASENAME: "landing",
TITLE: env.app.NAME,
Page: Landing,
},
...
}
Works fine everywhere else but here:
navbar-utils.ts
import { routes } from "../../config";
...
const navItems: NavItem[] = [
{
text: "Home",
icon: faHome,
to: routes.landing.PATH,
},
...
]
There is where Webpack loses it and keeps telling me that _config__WEBPACK_IMPORTED_MODULE_0__.routes is undefined.

React + Rollup - 'r is not defined'

Final edit: Thanks everyone for your help, however ultimately it was easier for me to transition to Webpack and Storybook. I'm leaving my original question untouched just in case it helps anyone in the future. Also, if anyone stumbles upon any issues configuring these (like I did), the link to the GitHub repo is below.
I'm creating a small lib using React and Rollup and trying to test locally with a CRA-powered project, however I'm facing this issue when importing a component from my library. I don't know if the problem is in my configuration or if this is a bug.
Uncaught ReferenceError: r is not defined
at Object.../dist/bundle.js (index.jsx:44)
Imported "Message" component where the error is happening
import React, { useEffect, useState } from 'react';
import { string, number, arrayOf } from 'prop-types';
import Container from './Container';
function Message({
text,
type,
timeout,
classes,
}) {
const [show, setShow] = useState(false);
useEffect(() => {
if (text && type) {
setShow(true);
setTimeout(() => setShow(false), timeout);
}
}, [text, type]);
const date = new Date();
return (
<Container
id={`message-${date}`}
key={`message-${date}`}
className={`${type}${classes?.map((className) => ` ${className}`)}`}
>
{
show
? (
<p>{text}</p>
) : ''
}
</Container>
);
}
// The source map points to this line when the error happens, but it still happens if I remove it and don't use prop-types, instead pointing to the closing bracket of the 'Message' function
Message.defaultProps = {
timeout: 3000,
classes: [],
};
Message.propTypes = {
text: string.isRequired,
type: string.isRequired,
timeout: number,
classes: arrayOf(string),
};
export default Message;
Test component where it's being used:
import React from 'react';
import { Message } from 'pure-ui';
import { getRandomArrayElement } from 'formatadores';
const types = [
'warning',
'error',
'success',
];
const texts = [
'This is a test',
'I will randomly display a message every so often, so stay sharp',
'Yet another test message',
];
const timeouts = [
5000,
3000,
1000,
];
function App() {
return (
<div>
<h1>Running...</h1>
<Message
type={getRandomArrayElement(types)}
text={getRandomArrayElement(texts)}
timeout={getRandomArrayElement(timeouts)}
/>
</div>
);
}
export default App;
rollup config file:
import babel from '#rollup/plugin-babel';
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import React from 'react';
import propTypes from 'prop-types';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
export default [
{
input: 'src/index.js',
watch: true,
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true,
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'prop-types': 'PropTypes',
},
},
plugins: [
external(),
babel({
exclude: 'node_modules/**',
presets: [
'#babel/preset-env',
['#babel/preset-react', { runtime: 'automatic' }],
],
}),
resolve({ extensions }),
commonjs({
namedExports: {
react: Object.keys(React),
'react/jsx-runtime': ['jsx', 'jsxs', 'Fragment'],
'react/jsx-dev-runtime': ['jsx', 'jsxs', 'jsxDEV'],
'prop-types': Object.keys(propTypes),
},
}),
],
external: [
'react',
'react-dom',
'prop-types',
],
},
];
I tried changing the namedExports (and also removing them), linking React from the lib to use the same version from the CRA project (in the lib both React and React DOM are listed as peer dependencies), but I always end with the same result. Is there something wrong with my config? This is the first time I use Rollup for creating a React component lib, so maybe there's something I missed
If the above info is insufficient, here's the GitHub repo
Thanks in advance
Edit: I just saw that I forgot to import React in my test project, however after doing so the results were the same, editing my original question just to fix that.
Update 1: I changed several configurations (changed deprecated rollup-plugins to their currently maintained versions, added globals to the output part of rollup.config.js, added namedExports to commonjs plugin configuration, added an external section specifying react, react-dom and prop-types), but now what I'm getting is a React is not defined error, updating the question with the new config

How to properly load i18n resources in next-i18next from api endpoints?

I have a nextjs app, which I want to extend using i18next and next-i18next (https://github.com/isaachinman/next-i18next).
The default configuration is looking for json files under ./public/locales/{lng}/{ns}.json, where lng is the language and ns a namespace.
My requirement however is, that this should be served from an api endpoint. I am struggling to find the correct configuration, as next-i18next does ignore my settings right now and is not firing off any xhr requests to my backend.
next-i18next.config.js:
const HttpApi = require('i18next-http-backend')
module.exports = {
i18n: {
defaultLocale: 'de',
locales: ['en', 'de'],
},
backend: {
referenceLng: 'de',
loadPath: `https://localhost:5001/locales/de/common`,
parse: (data) => {
console.log(data)
return data
}
},
debug: true,
ns: ['common', 'footer', 'second-page'], // the namespaces needs to be listed here, to make sure they got preloaded
serializeConfig: false, // because of the custom use i18next plugin
use: [HttpApi],
}
I am at a loss here. What am I doing wrong?
Eventually I cobbled it together.
const I18NextHttpBackend = require('i18next-http-backend')
module.exports = {
i18n: {
defaultLocale: 'de',
locales: ['de'],
backend: {
loadPath: `${process.env.INTERNAL_API_URI}/api/locales/{{lng}}/{{ns}}`
},
},
debug: true,
ns: ["common", "employees", "projects"],
serializeConfig: false,
use: [I18NextHttpBackend]
}
You might be running into an error saying You are passing a wrong module! Please check the object you are passing to i18next.use(). If this is the case, you can force the http backend to load as commonjs, by using the following import:
const I18NextHttpBackend = require('i18next-http-backend/cjs')
The first one worked on webpack 5, while I had to use the cjs import on webpack 4. Although I could not find the reason for this.
After this, its smooth sailing:
_app.tsx:
/*i18n */
import { appWithTranslation } from 'next-i18next'
import NextI18nextConfig from '../../next-i18next.config'
const MyApp = ({ Component, pageProps }: AppProps) => {
return (
<>
<MsalProvider instance={msalApp}>
<PageLayout>
<Component {...pageProps} />
</PageLayout>
</MsalProvider>
</>
)
}
export default appWithTranslation(MyApp, NextI18nextConfig)
anypage.tsx:
export const getServerSideProps: GetServerSideProps = async ({ locale }) => {
return {
props: {
...(await serverSideTranslations(locale, ['common', 'employees'])),
// Will be passed to the page component as props
},
};
}
If you just need to locales to be fetched once, during build, you can use getStaticProps instead - that is up to you.

msal-react TypeError: Failed to fetch

I'm using:
"#azure/msal-browser": "^2.11.2",
"#azure/msal-react": "^1.0.0-alpha.6"
My Configuration:
const configuration: Configuration = {
auth: {
clientId: CLIENT_ID,
authority: `${AUTHORITY}${TENANT}`,
redirectUri: window.location.origin,
},
cache: {
cacheLocation: BrowserCacheLocation.LocalStorage,
},
}
export const pca = new PublicClientApplication(configuration)
The App:
const authRequest = {
scopes: [
'openid',
'profile',
'User.Read'
],
}
const App = () => {
return (
<div>Nice</div>
)
}
const app = (
<MsalProvider instance={pca}>
<MsalAuthenticationTemplate
interactionType={InteractionType.Redirect}
authenticationRequest={authRequest}
errorComponent={ErrorComponent}
loadingComponent={LoadingComponent}>
<Router>
<StrictMode>
<App/>
</StrictMode>
</Router>
</MsalAuthenticationTemplate>
</MsalProvider>
)
The redirect works, I log in with the company account, then I'll be redirected back to the localhost. But:
getting the following error in the console:
TypeError: Failed to fetch
the LocalStorage:
{"failedRequests":[865,"ac1b77cf-4d4f-4917-a0cf-6e9fdda4a8f3"],"errors":["TypeError: Failed to fetch"],"cacheHits":0}
and the App component also doesn't render. The ErrorComponent is rendered.
Having the same issue with the sample:
https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/samples/msal-react-samples/typescript-sample
I've found out the CORS error in network:
Request URL: https://login.microsoftonline.com/******-aa2f-23**-****-************/oauth2/v2.0/token
That is weird, because the same redirect url works with react-adal.
I suppose the issue takes place because of wrong Azure App Configuration:
Manifest:
{
"allowPublicClient": null,
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false
}
oauth2AllowImplicitFlow should be definitely false.
Does anyone have a working example of the manifest for me please?
I ran into this issue a few days ago.
For me the issue was with the incorrect type of registered application. Please try by registering the application as a "Single-page" application instead of a "Web" application then you should not see this issue.

How to include browserHistory using ReactRouter in non-node app?

was experimenting with react and was replacing hashHistory with browserHostory. The application is a static application running on apache server and not on node. Have used the libraries for React, Reaact-dom, ReactRouter and created js pages for various routes. The replaced code doesn't seem working and on console got the message Uncaught ReferenceError: browserHistory is not defined . Below is he code for the same ? I want to replace hash history with browserHistory.
<script type="text/javascript">
var destination = document.querySelector("#container");
var { Router, Route, IndexRoute, IndexLink, Link } = ReactRouter;
ReactDOM.render(React.createElement(Router,{ history : browserHistory },React.createElement(
Route,{ path: "/", component: App },
React.createElement(IndexRoute, { component: Home }),
React.createElement(Route, { path: "/stuff", component: Stuff }),
React.createElement(Route, { path: "/contact", component: Contact }),
React.createElement(Route, { path: "/event", component: Event }),
React.createElement(Route, { path: "/search", component: Search }),
React.createElement(Route, { path: "/fetch", component: Fetch }),
React.createElement(Route, { path: "/socket", component: Socket }),
React.createElement(Route, { path: "/form", component: Form })
)
), destination);
</script>
If used node.js then could have imported the browserHistory, but here I am using react-router library in the html page. How to overcome this issue ?
You need to import browserHistory too.
var { Router, Route, IndexRoute, IndexLink, Link, browserHistory } = ReactRouter;

Resources