Testing event emitted from child component with Vitest & Vue-Test-Utils - vuejs3

I want to test if "onLogin" event emitted from child component will trigger "toLogin" function from parent correctly.
Login.vue
<template>
<ChildComponent
ref="child"
#onLogin="toLogin"
/>
</template>
<script>
import { useAuthStore } from "#/stores/AuthStore.js"; //import Pinia Store
import { userLogin } from "#/service/authService.js"; // import axios functions from another js file
import ChildComponent from "#/components/ChildComponent.vue";
export default {
name: "Login",
components: {
ChildComponent,
},
setup() {
const AuthStore = useAuthStore();
const toLogin = async (param) => {
try {
const res = await userLogin (param);
AuthStore.setTokens(res);
} catch (error) {
console.log(error);
}
};
}
</script>
login.spec.js
import { describe, it, expect, vi, beforeAll } from 'vitest';
import { shallowMount, flushPromises } from '#vue/test-utils';
import { createTestingPinia } from "#pinia/testing";
import Login from "#/views/user/Login.vue"
import { useAuthStore } from "#/stores/AuthStore.js";
describe('Login', () => {
let wrapper = null;
beforeAll(() => {
wrapper = shallowMount(Login, {
global: {
plugins: [createTestingPinia({ createSpy: vi.fn })],
},
});
})
it('login by emitted events', async () => {
const AuthStore = useAuthStore();
const loginParam = {
email: 'dummy#email.com',
password: '12345',
};
const spyOnLogin = vi.spyOn(wrapper.vm, 'toLogin');
const spyOnStore = vi.spyOn(AuthStore, 'setTokens');
await wrapper.vm.$refs.child.$emit('onLogin', loginParam);
await wrapper.vm.$nextTick();
await flushPromises();
expect(spyOnLogin).toHaveBeenCalledOnce(); // will not be called
expect(spyOnStore).toHaveBeenCalledOnce(); // will be called once
})
}
I expected both "spyOnLogin" and "spyOnStore" will be called once from emitted event, however, only "spyOnStore" will be called even though "spyOnStore" should only be called after "spyOnLogin" has been triggered.
The error message is:
AssertionError: expected "toLogin" to be called once
❯ src/components/__tests__:136:24
- Expected "1"
+ Received "0"
What do I fail to understand about Vitest & Vue-Test-Utils?

You shouldn't mock your toLogin method because its part of Login component which you are testing. Therefore, instead of expecting if toLogin has been called, you should check if instructions inside are working correctly.
In your case i would only test if after emit, userLogin and AuthStore.setTokens has been called.

Related

Vue3 - Pinia + Auth0 - isAuthenticated always false

I'm developing a vue3 app using pinia as state manager and auth0 as authprovider.
In my vue router, I've the following code to manage the authentication:
router.beforeEach(async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
const authStore = useAuthStore();
const isLogged = authStore.isLogged();
if (!isLogged) await handleNotLogged(to, from, next);
else await handleLogged(to, from, next);
});
async function handleNotLogged(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
const authStore = useAuthStore();
if (to?.query?.code && to?.query?.state) {
next({ name: '/logged/home' });
} else {
await authStore.login();
}
}
async function handleLogged(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {next()}
here is my authStore
import { defineStore } from 'pinia';
import { User } from '#models/user';
import { useStorage } from '#vueuse/core';
import { RouteLocation } from 'vue-router';
import { createAuth0 } from '#auth0/auth0-vue';
const authService = createAuth0({
domain: import.meta.env.VITE_APP_AUTH_URL,
client_id: import.meta.env.VITE_APP_AUTH_CLIENT_ID,
redirect_uri: `${window.location.origin}`,
});
const defaultUserData = {} as User;
const defaultLastRoute = { path: '/' } as RouteLocation;
export const useAuthStore = defineStore('AuthStore', {
state: () => ({
userData: useStorage('userData', defaultUserData, localStorage),
lastRoute: useStorage('lastRoute', defaultLastRoute, localStorage),
authService,
}),
actions: {
isLogged(): boolean {
try {
return this.authService.isAuthenticated;
} catch (error) {
return false;
}
},
async login(): Promise<boolean> {
try {
await this.authService.loginWithRedirect();
return true;
} catch (error) {
console.error(error);
return false;
}
},
async logout(): Promise<boolean> {
try {
await this.authService.logout();
return true;
} catch (error) {
console.error(error);
return false;
}
},
},
});
And also my main.ts
import App from './App.vue';
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import { registerPlugins } from '#plugins';
import { useAuthStore } from '#store/auth';
import router from '#router';
import vuetify from './plugins/vuetify';
async function main() {
const app = createApp(App);
registerPlugins();
const pinia = createPinia();
app.use(pinia);
const authStore = useAuthStore();
const { authService } = authStore;
app.use(authService);
app.use(router);
app.use(vuetify).mount('#app');
}
main();
The problem is that everytime the beforeEach is triggered, the auth0 isAuthenticated returns false. Even when i've just succesfully logged.
I've searched for some answers, and some said that ewhen there is a code and state in query params we should call the auth0.handleRedirectCallback but there's a note in the method saying
Note: The Auth0-Vue SDK handles this for you, unless you set skipRedirectCallback to true. In that case, be sure to explicitly call handleRedirectCallback yourself.
PS: The application in auth0 is configured as Single Page Application
There is already a topic with this question answered, I believe this one can help you:
Auth0 isAuthenticated() is always false

Next.js: Correct way to get dynamic route param when change triggered by Next.Link

I have a kanban app build with Next.js. I currently have two boards:
{"name": "New Board", "id": "6db0ceec-d371-4b53-8065-2eeebac4694a"}
{"name": "tired": "cc41d33e-43a1-49bd-8b76-18e46417b27a"}
I have a menu which maps over next Link, rendering links like so:
<Link href={`/board/${board.id}`}>{board.name}</Link>
I then have the following:
src/pages/board/[boardId].js (page)
src/pages/api/board/[boardId].js (API end point)
In the page, I've defined an async function which sends a GET request to the end point that retrieves the data. For SSR, it's called in getServerSideProps() (this would be called when a user navigates to a specific board page from another part of the app). For client-side, I call this in an effect. (This is called when the user is already on the board page but they select a different board from the menu).
The issue I am having is figuring out the correct Next.js idiomatic way to get the new id from the route when it is changed. I've tried using router.query and router.asPath. However, it often gives me the old value (before the route changed). The only way I am reliably able to get the correct param when the route changes is to use window.location.pathname.split('/')[2].
I will include the source code for the page as well as some console.log() output which will show how the three methods of getting the id from the route are inconsistent (window is always correct) as I switch back and forth between the two boards by clicking the Links in the menu:
// src/pages/board/[boardId].js
import React, { useEffect, useState } from 'react'
import { useDispatch } from 'react-redux'
import supabase from 'Utilities/SupabaseClient'
import Board from 'Components/Screens/Board/Board'
import { useRouter } from 'next/router'
import axios from 'axios'
import { getBaseUrl } from 'Utilities'
import { hydrateTasks } from 'Redux/Reducers/TaskSlice'
const BoardPage = (props) => {
const router = useRouter()
const dispatch = useDispatch()
async function handleRouteChange() {
const { asPath } = router
const { boardId } = router.query // sometimes this does not update!
const idFromWindow = window.location.pathname.split('/')[2]
const { board, tasks } = await handleFetchData({boardId: idFromWindow})
console.log(`hello from handleRouteChange:\n\nFrom window: ${idFromWindow}\n\nFrom router.query: ${boardId}\n\nFrom router.asPath: ${asPath}`)
dispatch(hydrateTasks({board, tasks}))
}
useEffect(() => {
//subscribe
router.events.on('routeChangeComplete', handleRouteChange);
//unsubscribe
return () => router.events.off('routeChangeComplete', handleRouteChange);
}, [ router.events]);
return (
<Board {...props}/>
)
}
const handleFetchData = async ({boardId, req}) => {
const baseUrl = getBaseUrl(req)
return axios.get(`${baseUrl}/api/board/${boardId}`)
.then(({data}) => data)
.catch(err => { console.log(err)})
}
export async function getServerSideProps ({ query, req }) {
const { user } = await supabase.auth.api.getUserByCookie(req)
if (!user) {
return { props: {}, redirect: { destination: '/signin' } }
}
const { boardId } = query
const { board, tasks} = await handleFetchData({boardId, req})
return { props: { user, board, tasks } }
}
export default BoardPage
Starting from the "tired" board, I click back and forth between "New Board" and "tired". Observe the console output. The window is always correct. The router is frequently wrong:
// click 1
[boardId].js?0a51:19 hello from handleRouteChange:
From window: 6db0ceec-d371-4b53-8065-2eeebac4694a
From router.query: cc41d33e-43a1-49bd-8b76-18e46417b27a
From router.asPath: /board/cc41d33e-43a1-49bd-8b76-18e46417b27a
// click 2
[boardId].js?0a51:19 hello from handleRouteChange:
From window: cc41d33e-43a1-49bd-8b76-18e46417b27a
From router.query: cc41d33e-43a1-49bd-8b76-18e46417b27a
From router.asPath: /board/cc41d33e-43a1-49bd-8b76-18e46417b27a
// click 3
[boardId].js?0a51:19 hello from handleRouteChange:
From window: 6db0ceec-d371-4b53-8065-2eeebac4694a
From router.query: cc41d33e-43a1-49bd-8b76-18e46417b27a
From router.asPath: /board/cc41d33e-43a1-49bd-8b76-18e46417b27a
// click 4
[boardId].js?0a51:19 hello from handleRouteChange:
From window: cc41d33e-43a1-49bd-8b76-18e46417b27a
From router.query: cc41d33e-43a1-49bd-8b76-18e46417b27a
From router.asPath: /board/cc41d33e-43a1-49bd-8b76-18e46417b27a
I'm new to Next.js, so it's possible I am going about this the wrong way...
How I have done this is -
Suppose I have a page called localhost:3000/board
I have done this with state, and not with [boardId] (lets called this state as boardId and initialvalue be null)
Suppose a user from anywhere in the app visit this page, using the Link
<Link href="/board">
Go To Board
</Link>
on the page mount I try to read the value of boardId from url such as -
useEffect(() => {
if (router.query && router.query.boardId )
{
setBoardId(router.query.boardId);
}
}, []);
and if fount I set the state of boardId, also I do this to get the data from API
useEffect(() => {
if (boardId) getBoardIdDataFromApi();
}, [boardId] );
In the above Case the board Id will be null as I'm not passing any Id as params to the url. (In my case I create a new board here)
Case 2 - suppose a User visit this board page with something like this, from anywhere in the page -
<Link
href={{
pathname: "/board",
query: { boardId: boardId },
}}
>
this time url will be like
localhost:3000?boardId=AnyBoardId
and this will load the Id and get actual data from the api, or change the layout accodringingly.
useEffect(() => {
if (router.query && router.query.boardId )
{
setBoardId(router.query.boardId);
}
}, []);
Case - 3
Now when a user change the boaardId fromt being on the page itself, you can do -
const onChangeBoard = (v) => {
router.push('/board?boardId=${v}', undefined, { shallow: true })
setboardId(v);
}
This will upadte the state of boardId and fetch the data once the user chooses a different board and update the url.
I'm experimenting with {shallow:true}, and I have all the data fetching mechanisms on the client side.
For you -
you can block getServerSideProps for Case 1
Use getServerSideProps for case 2
For case 3, if you remove shallow, you can again use getServerSideProps but please verify.
This may not be the exact answer. but can help you to understand the logic
Okay I got this working by checking the effect to:
useEffect(() => {
async function handleRouteChange() {
const { boardId } = router.query
const { board, tasks } = await handleFetchData({ boardId })
dispatch(hydrateTasks({ board, tasks }))
}
handleRouteChange()
}, [router])
Here is the complete code for the page now:
// src/pages/board/[boardId].js
import React, { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import supabase from 'Utilities/SupabaseClient'
import Board from 'Components/Screens/Board/Board'
import { useRouter } from 'next/router'
import axios from 'axios'
import { getBaseUrl } from 'Utilities'
import { hydrateTasks } from 'Redux/Reducers/TaskSlice'
const BoardPage = (props) => {
const router = useRouter()
const dispatch = useDispatch()
useEffect(() => {
async function handleRouteChange() {
const { boardId } = router.query
const { board, tasks } = await handleFetchData({ boardId })
dispatch(hydrateTasks({ board, tasks }))
}
handleRouteChange()
}, [router])
return (
<Board {...props}/>
)
}
const handleFetchData = async ({boardId, req}) => {
const baseUrl = getBaseUrl(req)
return axios.get(`${baseUrl}/api/board/${boardId}`)
.then(({data}) => data)
.catch(err => { console.log(err)})
}
export async function getServerSideProps ({ query, req }) {
const { user } = await supabase.auth.api.getUserByCookie(req)
if (!user) {
return { props: {}, redirect: { destination: '/signin' } }
}
const { boardId } = query
const { board, tasks} = await handleFetchData({boardId, req})
return { props: { user, board, tasks } }
}
export default BoardPage

Not fetch data using getStaticProps in Nextjs [duplicate]

Below is the code located at "Pages/home.js". // localhost:3000/home
import axios from 'axios';
import Section1 from '../components/home-sections/section-1';
const Homepage = ({ show }) => {
const Html = JSON.parse(show.response.DesktopHTML);
const renderSection = () => {
return Html.map((itemData,index)=>{
return(<div key={index}>{itemData.DisplayName}</div>)
})
}
return(
<div>
{ renderSection()}
<Section1 />
</div>
)
}
export const getServerSideProps = async ({ query }) => {
try {
const response = await axios.get(
`https://api.example.com/getHomeSection?title=Section 1`
);
return {
props: {
show: response.data,
},
};
} catch (error) {
return {
props: {
error: error.error,
},
};
}
};
export default Homepage;
Now same code I added into section-1.js and this file is located to "components/home-sections/section-1.js"
Now getServerSideProps is working fine in home.js, but in section-1.js it is not working.
Error: TypeError: show is undefined in section-1.js
You cannot use getServerSideProps in non-page components. You can either pass the prop from Home to HomeSection or create a context so the value can be available globally from the component tree
getServerSideProps can only be exported from a page. You can’t export
it from non-page files.
https://nextjs.org/docs/basic-features/data-fetching#only-allowed-in-a-page-2
getServerSideProps can only be exported from Page components. It will not be run on components imported into a page.
However, you could export a function from the component that returns the props, and call that function from the page's getServerSideProps function.
Create a getServerSideProps function on the component.
// #components/MyComponent.tsx
import { GetServerSidePropsContext } from 'next';
function MyComponent(props: IMyComponentProps) {
return (<div>MyComponent</div>;)
}
MyComponent.getServerSideProps = async (context: GetServerSidePropsContext): Promise<{ props: IMyComponentProps }> => {
return { props: { ... } };
}
export default MyComponent;
In your page's getServerSideProps function, call the component's getServerSideProps function and merge the props from the component with the props from the page.
// mypage.tsx
import MyComponent from '#components/MyComponent';
const Page: NextPageWithLayout = (props: IIndexPageProps) => {
return <MyComponent />;
}
export async function getServerSideProps(context: GetServerSidePropsContext): Promise<{ props: IIndexPageProps }> {
let componentServerSideProps = await MyComponent.getServerSideProps(context);
let otherServerSideProps = { props: { ... } };
return {
props: {
...componentServerSideProps.props,
...otherServerSideProps.props
}
};
}

NEXTJS: getServerSideProps not working into components

Below is the code located at "Pages/home.js". // localhost:3000/home
import axios from 'axios';
import Section1 from '../components/home-sections/section-1';
const Homepage = ({ show }) => {
const Html = JSON.parse(show.response.DesktopHTML);
const renderSection = () => {
return Html.map((itemData,index)=>{
return(<div key={index}>{itemData.DisplayName}</div>)
})
}
return(
<div>
{ renderSection()}
<Section1 />
</div>
)
}
export const getServerSideProps = async ({ query }) => {
try {
const response = await axios.get(
`https://api.example.com/getHomeSection?title=Section 1`
);
return {
props: {
show: response.data,
},
};
} catch (error) {
return {
props: {
error: error.error,
},
};
}
};
export default Homepage;
Now same code I added into section-1.js and this file is located to "components/home-sections/section-1.js"
Now getServerSideProps is working fine in home.js, but in section-1.js it is not working.
Error: TypeError: show is undefined in section-1.js
You cannot use getServerSideProps in non-page components. You can either pass the prop from Home to HomeSection or create a context so the value can be available globally from the component tree
getServerSideProps can only be exported from a page. You can’t export
it from non-page files.
https://nextjs.org/docs/basic-features/data-fetching#only-allowed-in-a-page-2
getServerSideProps can only be exported from Page components. It will not be run on components imported into a page.
However, you could export a function from the component that returns the props, and call that function from the page's getServerSideProps function.
Create a getServerSideProps function on the component.
// #components/MyComponent.tsx
import { GetServerSidePropsContext } from 'next';
function MyComponent(props: IMyComponentProps) {
return (<div>MyComponent</div>;)
}
MyComponent.getServerSideProps = async (context: GetServerSidePropsContext): Promise<{ props: IMyComponentProps }> => {
return { props: { ... } };
}
export default MyComponent;
In your page's getServerSideProps function, call the component's getServerSideProps function and merge the props from the component with the props from the page.
// mypage.tsx
import MyComponent from '#components/MyComponent';
const Page: NextPageWithLayout = (props: IIndexPageProps) => {
return <MyComponent />;
}
export async function getServerSideProps(context: GetServerSidePropsContext): Promise<{ props: IIndexPageProps }> {
let componentServerSideProps = await MyComponent.getServerSideProps(context);
let otherServerSideProps = { props: { ... } };
return {
props: {
...componentServerSideProps.props,
...otherServerSideProps.props
}
};
}

"Cannot read property of undefined" being thrown by react-apollo used with React-NextJS

My NextJS project has been giving me grief over Graph QL these days. I've been trying to implement an Apollo client solution to retrieve data from a remote GraphQL server into a custom component. But no matter which solution I try, I always end up with this error. Here's my current react-apollo implementation:
// /lib/with-apollo-client.js
import React from "react";
import Head from "next/head";
import { getDataFromTree } from "react-apollo";
import initApollo from "./init-apollo";
export default App => {
return class WithData extends React.Component {
static displayName = `WithData(${App.displayName})`;
static async getInitialProps(ctx) {
const { Component, router } = ctx;
const apollo = initApollo({});
ctx.ctx.apolloClient = apollo;
let appProps = {};
if (App.getInitialProps) {
appProps = await App.getInitialProps(ctx);
}
// Run all GraphQL queries in the component tree
// and extract the resulting data
if (!process.browser) {
try {
// Run all GraphQL queries
await getDataFromTree(
<App
{...appProps}
Component={Component}
router={router}
apolloClient={apollo}
/>
);
} catch (error) {
console.error("Error while running `getDataFromTree`", error);
}
// getDataFromTree does not call componentWillUnmount
// head side effect therefore need to be cleared manually
Head.rewind();
}
// Extract query data from the Apollo store
const apolloState = apollo.cache.extract();
return {
...appProps,
apolloState
};
}
constructor(props) {
super(props);
this.apolloClient = initApollo(props.apolloState);
}
render() {
return <App {...this.props} apolloClient={this.apolloClient} />;
}
};
};
// /lib/init-apollo.js
import { ApolloClient, InMemoryCache, HttpLink } from 'apollo-boost'
import fetch from 'isomorphic-unfetch'
let apolloClient = null
// Polyfill fetch() on the server (used by apollo-client)
if (!process.browser) {
global.fetch = fetch
}
function create (initialState) {
// Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
return new ApolloClient({
connectToDevTools: process.browser,
ssrMode: !process.browser, // Disables forceFetch on the server (so queries are only run once)
link: new HttpLink({
uri: 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', // Server URL (must be absolute)
credentials: 'same-origin' // Additional fetch() options like `credentials` or `headers`
}),
cache: new InMemoryCache().restore(initialState || {})
})
}
export default function initApollo (initialState) {
// Make sure to create a new client for every server-side request so that data
// isn't shared between connections (which would be bad)
if (!process.browser) {
return create(initialState)
}
// Reuse client on the client-side
if (!apolloClient) {
apolloClient = create(initialState)
}
return apolloClient
}
The component I'm retrieving data into looks like this:
// /components/PostsList2.jsx
import { Query } from 'react-apollo'
import gql from 'graphql-tag'
export const allUsersQuery = gql`
query allUsers($first: Int!, $skip: Int!) {
allUsers(orderBy: createdAt_DESC, first: $first, skip: $skip) {
id
firstName
createdAt
}
_allUsersMeta {
count
}
}
`
export const allUsersQueryVars = {
skip: 0,
first: 10
}
export default function PostsList2 () {
return (
<Query query={allUsersQuery} variables={allUsersQueryVars}>
{({ loading, error, data: { allUsers, _allUsersMeta }, fetchMore }) => {
if (error) return <aside>Error loading users!</aside>
if (loading) return <div>Loading</div>
const areMorePosts = allUsers.length < _allUsersMeta.count
return (
<section>
<ul>
{allUsers.map((user, index) => (
<li key={user.id}>
<div>
<span>{index + 1}. </span>
<div>{user.firstName}</div>
</div>
</li>
))}
</ul>
{areMorePosts ? (
<button onClick={() => loadMorePosts(allUsers, fetchMore)}>
{' '}
{loading ? 'Loading...' : 'Show More'}{' '}
</button>
) : (
''
)}
</section>
)
}}
</Query>
)
}
function loadMorePosts (allUsers, fetchMore) {
fetchMore({
variables: {
skip: allUsers.length
},
updateQuery: (previousResult, { fetchMoreResult }) => {
if (!fetchMoreResult) {
return previousResult
}
return Object.assign({}, previousResult, {
// Append the new users results to the old one
allUsers: [...previousResult.allUsers, ...fetchMoreResult.allUsers]
})
}
})
}
Since this is a NextJS project, there's also an _app.jsx that I've wrapped in a special provider component:
// /pages._app.jsx
/* eslint-disable max-len */
import '../static/styles/fonts.scss';
import '../static/styles/style.scss';
import '../static/styles/some.css';
import CssBaseline from '#material-ui/core/CssBaseline';
import { ThemeProvider } from '#material-ui/styles';
import jwt from 'jsonwebtoken';
import withRedux from 'next-redux-wrapper';
import App, {
Container,
} from 'next/app';
import Head from 'next/head';
import React from 'react';
import { Provider } from 'react-redux';
import makeStore from '../reducers';
import mainTheme from '../themes/main-theme';
import getSessIDFromCookies from '../utils/get-sessid-from-cookies';
import getLanguageFromCookies from '../utils/get-language-from-cookies';
import getUserTokenFromCookies from '../utils/get-user-token-from-cookies';
import removeFbHash from '../utils/remove-fb-hash';
import withApolloClient from '../lib/with-apollo-client'
import { ApolloProvider } from 'react-apollo'
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let userToken;
let sessID;
let language;
if (ctx.isServer) {
ctx.store.dispatch({ type: 'UPDATEIP', payload: ctx.req.headers['x-real-ip'] });
userToken = getUserTokenFromCookies(ctx.req);
sessID = getSessIDFromCookies(ctx.req);
language = getLanguageFromCookies(ctx.req);
const dictionary = require(`../dictionaries/${language}`);
ctx.store.dispatch({ type: 'SETLANGUAGE', payload: dictionary });
if(ctx.res) {
if(ctx.res.locals) {
if(!ctx.res.locals.authenticated) {
userToken = null;
sessID = null;
}
}
}
if (userToken && sessID) { // TBD: validate integrity of sessID
const userInfo = jwt.verify(userToken, process.env.JWT_SECRET);
ctx.store.dispatch({ type: 'ADDUSERINFO', payload: userInfo });
}
ctx.store.dispatch({ type: 'ADDSESSION', payload: sessID }); // component will be able to read from store's state when rendered
}
const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};
return { pageProps };
}
componentDidMount() {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentNode.removeChild(jssStyles);
}
// Register serviceWorker
if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/serviceWorker.js'); }
// Handle FB's ugly redirect URL hash
removeFbHash(window, document);
}
render() {
const { Component, pageProps, store, apolloClient } = this.props;
return (
<Container>
<Head>
// redacted for brevity
</Head>
<ThemeProvider theme={mainTheme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<ApolloProvider client={apolloClient}>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</ApolloProvider>
</ThemeProvider>
</Container>
);
}
}
export default withApolloClient(withRedux(makeStore)(MyApp));
So with this setup, when I compile and run my app, it throws the following:
TypeError: Cannot read property 'allUsers' of undefined
I'm really lost! The repo is up at https://github.com/amitschandillia/proost/tree/master/web.

Resources