Uncaught TypeError: require.ensure is not a function at Object.getComponent (ECMASCRIPT) - meteor

Am porting over my meteor project to use ecmascript instead of using webpack / babel. Also upgrading my meteor (from 1.4 to 1.7) and react (from 15.3.2 to 16.8.6) too.
routes.jsx
import * as React from 'react';
export default function (injectDeps, {Store, Routes}) {
const route = {
path: 'tickets',
onEnter: (nextState, replace) => {
if (!Meteor.userId() || !Roles.userIsInRole(Meteor.userId(), 'staff', Roles.GLOBAL_GROUP)) {
replace('/login');
}
},
getComponent(nextState, cb) {
require.ensure([], (require) => {
Store.injectReducer('tickets', require('./reducers'));
cb(null, require('./containers/list.js'));
}, 'tickets');
},
childRoutes: [
{
path: ':_id',
getComponent(nextState, cb) {
require.ensure([], (require) => {
Store.injectReducer('tickets', require('./reducers'));
cb(null, require('./containers/view.js'));
}, 'tickets.view');
}
}
]
};
Routes.injectChildRoute(route);
}
Got this error:
Uncaught TypeError: require.ensure is not a function
at Object.getComponent (routes.jsx:20)
at getComponentsForRoute (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:38035)
at modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:38053
at modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37842
at Array.forEach (<anonymous>)
at mapAsync (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37841)
at getComponents (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:38052)
at finishEnterHooks (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37263)
at next (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37810)
at loopAsync (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37814
Any suggestion how to port this?

This is how it was done to get rid of require.ensure:
routes.jsx (final)
{
path: 'config',
getComponent(nextState, cb) {
import('./containers/config').then(mod => {
Store.injectReducer('config', require('./reducers/config').default);
cb(null, mod.default);
});
}
}
NOTE:
1) This is how the to migrate from require.ensure (used by webpack) to without relying on webpack (which was my case as am fully using Meteor Atmosphere to run)
2) mod and require(...).xxx had changed to mod.default and require(...).default if reducer function is exported as export default, otherwise said reducer will not be called.

Related

Auto-import vue reactivity system in vitest for testing composables in Nuxt 3 and vitest

I am using some utils in Nuxt 3. The vue reactivity system (ref, computed, ...) is also imported directly. However, it is not the case for the tests.
Running the spec file importing a ./useBusinessValidation composable throws the error ReferenceError: ref is not defined
Source file ./useBusinessValidation:
import { MaybeRef } from "#vueuse/core"
export const useBusinessValidation = <T>(rule: (payload: T) => true | string, payload: MaybeRef<T>) => {
const validation = computed(() => rule(unref(payload)))
const isValid = computed(() => validation.value === true)
const errorMessage = computed(() => isValid.value ? undefined : validation.value as string)
return {
isValid,
errorMessage
}
}
Spec file useBusinessValidation.spec.ts:
import { useBusinessValidation } from "./useBusinessValidation"
describe('useBusinessValidation', async () => {
it('should be valid with payload respecting the rule', () => {
const rule = (x: number) => x > 0 ? true : `invalid ${x} number. Expected ${x} to be greater than 0.`
const { isValid, errorMessage } = useBusinessValidation(rule, 0)
expect(isValid.value).toBe(true)
expect(errorMessage.value).toBe(undefined)
});
})
and the vitest.config.ts
{
resolve: {
alias: {
'~': '.',
'~~': './',
'##': '.',
'##/': './',
'assets': './assets',
'public': './public',
'public/': './public/'
}
},
test: {
globals: true,
setupFiles: './test/setupUnit.ts',
environment: 'jsdom',
deps: { inline: [/#nuxt\/test-utils-edge/] },
exclude: [
'test/**/**.spec.ts',
'**/node_modules/**',
'**/dist/**',
'**/cypress/**',
'**/.{idea,git,cache,output,temp}/**'
]
}
}
I also tried with the #vitejs/plugin-vue as
plugins: [Vue()]
in the vitest config. It didn't work out.
To auto-import in vitest, install the unplugin-auto-import.
Then, in the vitest.config.ts add:
import AutoImport from 'unplugin-auto-import/vite';
export default defineConfig({
...
plugins: [
AutoImport({
imports: [
'vue',
// could add 'vue-router' or 'vitest', whatever else you need.
],
}),
]
});

NextJS routing error, when changing pages, the wrong file is trying to open

What I want
I want to change pages without next thinking I am trying to open another page.
The Problem
I have this weird routing problem.
First, my folder structure
pages
[app]
[object]
index.js
index.js
manager.js
feed.js
I am at this path /[app] and navigate to /[app]/manager and then I want to navigate to /[app]/feed and I get this Unhandled Runtime Error.
TypeError: Cannot read property "title" of undefined
This error comes from [object] index.js. Stacktrace is below. Of course, it makes sense it cannot read title because I am trying to open another page. And yet it thinks I am trying to open [object].
This error happens from time to time, but it doesn't matter in what order I try to open the pages, it can be manager to feed or feed to manager, or whatever else I have there.
My getStaticPaths and getStaticProps are the same on all these pages, I will share the one for manager.js.
export const getStaticPaths = async () => {
const paths = appRoutes.map((appRoute) => {
const slug = appRoute.slug;
return {
params: {
app: slug,
manager: 'manager',
},
};
});
return {
fallback: false,
paths,
};
};
export const getStaticProps = async ({ locale }) => {
return {
props: {
...(await serverSideTranslations(locale, ['manager', 'common'])),
},
};
};
And the same again, but for [object]:
export const getStaticPaths = async () => {
const allObjects = await loadObjectData({ id: 'all' });
const paths = allObjects.flatMap((object) => {
return appRoutes.map((appRoute) => {
return {
params: {
object: object.type,
app: appRoute.slug,
},
};
});
});
return {
fallback: false,
paths,
};
};
export const getStaticProps = async ({ params, locale }) => {
const object = await loadObjectData({ type: params.object });
const app = appRoutes.find((appRoute) => appRoute?.slug === params.app);
if (!object) {
throw new Error(
`${object} is not a valid Object. Try checking out your parameters: ${params.object}`
);
}
if (!app) {
throw new Error(`${app} is not a valid App.`);
}
return {
props: {
...(await serverSideTranslation(locale, ['common'])),
object,
app,
},
};
};
This error is hard to reproduce because it happens only from time to time.
New Edits
This is the full file of [object]/index.js
import appRoutes from '../../../routes/appRoutes';
import loadObjectData from '../../../utils/loadObjects';
import { serverSideTranslation } from 'next-i18next/serverSideTranslations';
export default function ObjectPage({ object }) {
return <h1> {object.title} </h1>;
}
export const getStaticPaths = async () => {
const allObjects = await loadObjectData({ id: 'all' });
const paths = allObjects.flatMap((object) => {
return appRoutes.map((appRoute) => {
return {
params: {
object: object.type,
app: appRoute.slug,
},
};
});
});
return {
fallback: false,
paths,
};
};
export const getStaticProps = async ({ params, locale }) => {
const object = await loadObjectData({ type: params.object });
const app = appRoutes.find((appRoute) => appRoute?.slug === params.app);
if (!object) {
throw new Error(
`${object} is not a valid Object. Try checking out your parameters: ${params.object}`
);
}
if (!app) {
throw new Error(`${app} is not a valid App.`);
}
return {
props: {
...(await serverSideTranslation(locale, ['common'])),
object,
app,
},
};
};
Stacktrace:
ObjectPage: index.js:6 Uncaught TypeError: Cannot read property 'title' of undefined
at ObjectPage (http://localhost:3000/_next/static/chunks/pages/%5Bapp%5D/%5Bobject%5D.js:3733:21)
at div
at Grid (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:13654:35)
at WithStyles (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:179881:31)
at div
at StyledComponent (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:179652:28)
at div
at ProjectSelectionStore (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:234820:77)
at Layout (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:278:23)
at TaskStore (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:235454:77)
at UserDocumentStore (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:235663:77)
at StoneStore (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:235119:77)
at StoreMall (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:409:23)
at ThemeProvider (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:178584:24)
at App (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:234333:24)
at I18nextProvider (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:224427:19)
at AppWithTranslation
at ErrorBoundary (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:146:47)
at ReactDevOverlay (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:250:23)
at Container (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:8662:5)
at AppContainer (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:9151:24)
at Root (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:9282:24)
25.06.2021
So I consoled logged the router from the ObjectPage and for each NavigationItem. I noticed something strange.
This is the href I am passing to teh <Link>:
{
pathname: "/[app]/[menuItem]"
query: {
app: "content"
menuItem: "files"
}
}
And this is the full router I am getting back on ObjectPage.
{
asPath: "/content/editor" // this the path i want to open
back: ƒ ()
basePath: ""
beforePopState: ƒ ()
components: {
"/[app]/[object]": {styleSheets: Array(0), __N_SSG: true, __N_SSP: undefined, props: {…}, Component: ƒ}
"/[app]/editor": {initial: true, props: {…}, err: undefined, __N_SSG: true, Component: ƒ, …}
"/_app": {styleSheets: Array(0), Component: ƒ}
}
defaultLocale: "de"
events: {on: ƒ, off: ƒ, emit: ƒ}
isFallback: false
isLocaleDomain: false
isPreview: false
isReady: true
locale: "de"
locales: ["de"]
pathname: "/[app]/[object]" // [object] is being loaded
prefetch: ƒ ()
push: ƒ ()
query: {app: "content", menuItem: "editor", object: "editor"} // this is interesting
reload: ƒ ()
replace: ƒ ()
route: "/[app]/[object]" // same as pathname
}
In the query you can see object was injected. But I cannot tell from where and why.
I had this code:
{
pathname: "/[app]/[menuItem]"
query: {
app: "content"
menuItem: "files"
}
}
This was incorrect because there is no dynamic path to [menuItem]. So instead I wrote:
{
pathname: "/[app]/files"
query: {
app: "content"
}
}
Which fixed the issue I had.
I have misunderstood the docs for parameters.

Problem With Redux's Store.dispatch Doesn't Get Updated

Upgrading meteor (from 1.4 to 1.7) and react (from 15.3.2 to 16.8.6).
"react-redux": "^4.4.10"
"redux": "3.5.2"
I found my codes were unable to update/store using Store.dispatch(), the Store just not updated.
My ACTIONS file as below:
actions/config.js
...
export default {
load({Meteor, Store}) {
return new Promise((resolve, reject) => {
Meteor.call('variables.load', null, (err, data) => {
if (err) {
reject({_error: err.reason });
return;
}
console.log("************ Store (A) = "+JSON.stringify(Store.getState()))
Store.dispatch({
type: LOAD_CONFIG,
data
});
resolve();
console.log("************ Store (B) = "+JSON.stringify(Store.getState()))
});
});
},
...
Both the console.log() were having the following:
Store (A) = {"router":{"locationBeforeTransitions":{"pathname":"/settings/config","search":"","hash":"","action":"PUSH","key":"zif4ls","basename":"/crm","query":{}}},"form":{"config":{"syncErrors":{"reportLimit":"Required"}}},"loadingBar":{}}
Store (B) = {"router":{"locationBeforeTransitions":{"pathname":"/settings/config","search":"","hash":"","action":"PUSH","key":"zif4ls","basename":"/crm","query":{}}},"form":{"config":{"syncErrors":{"reportLimit":"Required"}}},"loadingBar":{}}
Which I do expect it will have something like "reportLimit":6 , which was confirmed to have loaded into the data variable. Instead, I was getting the following error in browser console:
Uncaught TypeError: Cannot read property 'data' of undefined
Is there anything wrong/breaking changes you could think of? As these codes had been working before the upgrade.
EDIT:
I've further narrowed down the problem. It may seems to be my Routes is not calling the Reducer.
I've since change the code in my Routes to remove the need to use require.ensure .
routes.jsx (prior)
{
path: 'config',
getComponent(nextState, cb) {
require.ensure([], (require) => {
Store.injectReducer('config', require('./reducers').config)
cb(null, require('./containers/config.js'))
}, 'config')
}
},
routes.jsx (latest, to get rid of require.ensure)
{
path: 'config',
getComponent(nextState, cb) {
import('./containers/config.js')
.then(mod => {Store.injectReducer('config', require('./reducers').config);
cb(null, mod);});
}
},
Then I notice that in the reducer:
reducer/config.js
// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
[LOAD_CONFIG]: (state, action) => ({
...state,
data: action.data
})
};
// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
data: null
};
export default function configReducer(state = initialState, action) {
console.log("************ Reducer")
const handler = ACTION_HANDLERS[action.type];
return handler ? handler(state, action) : state;
}
As per logged, function configReducer doesn't seem to have been called elsewhere.
After much trial-and-error, confirmed the problem is with the routing part, final changes:
routes.jsx (final)
{
path: 'config',
getComponent(nextState, cb) {
import('./containers/config').then(mod => {
Store.injectReducer('config', require('./reducers/config').default);
cb(null, mod.default);
});
}
}
Key points:
1) This is how the to migrate from require.ensure (used by webpack) to without relying on webpack (which was my case as am fully using Meteor Atmosphere to run)
2) mod and require(...).xxx had changed to mod.default and require(...).default if reducer function is exported as export default, otherwise said reducer will not be called.
Really took me weeks to figure this out!
Try this:
Store.dispatch({
type: LOAD_CONFIG,
data: data
});

React Native - Warning: Possible Unhandled Promise Rejection (id: 0)

Warning: Possible Unhandled Promise Rejection (id: 0)
TypeError: Object is not a function (evaluating 'concreteComponentProvider()')
This is the Warning I get after adding React Redux in my App. It might some conflict about the React Redux and React Native Navigation (latest version) or also the React Native Vector Icons.
I think what causing the Error is in this code, the startMainTabs.js. This is where I code all my React Native Navigation.
Feel free to ask for more of my codes or any questions. Thank you!
These are my codes:
App.js
import {Provider} from 'react-redux';
import configureStore from './src/store/configureStore';
const store = configureStore();
//Register Screens
Navigation.registerComponent("Event.AuthScreen", () => AuthScreen);
Navigation.registerComponent("Event.Map", () => EventMap);
Navigation.registerComponent("EventCreator", () => EventCreator, store, Provider);
Navigation.registerComponent("EventHome", () => EventHome, store, Provider);
Navigation.setRoot({
root: {
stack: {
children: [{
component: {
name: "Event.AuthScreen",
}
}],
options: {
topBar: {
title: {
text: 'Welcome'
}
}
}
}
}
});
startMainTabs.js
const startTabs = () => {
Promise.all([
Icon.getImageSource("ios-home", 30),
Icon.getImageSource("ios-map", 30),
Icon.getImageSource("ios-share-alt", 30)
]).then(sources => {
Navigation.setRoot({
root: {
bottomTabs: {
children: [{
stack: {
children: [{
component: {
name: "Event.Map",
}
}],
options: {
bottomTab: {
icon: sources[1],
testID: 'FIRST_TAB_BAR_BUTTON'
}
}
}
},
{
stack: {
children: [{
component: {
name: "EventHome"
}
}],
options: {
bottomTab: {
icon: sources[0],
testID: 'SECOND_TAB_BAR_BUTTON'
}
}
}
},
{
component: {
name: "EventCreator",
options: {
bottomTab: {
icon: sources[2],
testID: 'THIRD_TAB_BAR_BUTTON'
}
}
}
}
]
}
}
});
})
}
in newest version of react native navigation from wix you should use
registerComponentWithRedux instead of registerComponent,
and set Provider before store
Navigation.registerComponentWithRedux("Event.AuthScreen", () => AuthScreen,Provider,store);
Navigation.registerComponentWithRedux("Event.Map", () => EventMap,Provider,store);
Navigation.registerComponentWithRedux("EventCreator", () => EventCreator,Provider,store);
Navigation.registerComponentWithRedux("EventHome", () => EventHome,Provider,store);
In the newest version of the RNN you should use registerComponentWithRedux instead of registerComponent and the Provider comes first then store, like the above code example

Meteor Subscription undefined in react component

I am using meteor + react and am trying to subscribe to data on the client side. However, I keep getting the error that the collection I am trying to return is undefined.
My server.js:
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { check } from 'meteor/check';
export const Reminders = new Mongo.Collection('reminders');
Meteor.publish('reminders', function() {
return Reminders.find();
});
My Reminders.jsx file:
RemindersList = React.createClass({
mixins: [ReactMeteorData],
getInitialState: function() {
return {
reminders: [
{
name: 'Pill 1',
description: 'Pill 1 description',
time: '9am'
},
{
name: 'Pill 2',
description: 'Pill 2 description',
time: '9am'
},
{
name: 'Pill 3',
description: 'Pill 3 description',
time: '9am'
}
]
}
},
getMeteorData: function() {
var data = {};
var handle = Meteor.subscribe('reminders');
if(handle.ready()) {
data.reminders = Reminders.findOne(); //Returns `Reminders` is not defined
}
return data;
},
render: function() {
console.log(this.data); //returns an empty object
return (
<h1>Test</h1>
)
}
});
The specific error I am getting is in the getMeteorData function:
Reminders is not defined.
However, I clearly define Reminders in my server.js file. Does anyone know what might be wrong?
Thanks in advance!!
Your collection is only defined on server side. You'll need to put it in a file that's accessible on both sides and import it from both server and client side code.

Resources