Remix - Error: Cannot initialize 'routeModules' - remix.run

I have the following code in a route file:
import { Success } from '#web/components/Success'
export { meta } from '#web/utils/meta'
export { loadPageContent as loader } from '#web/utils/loadContent'
export default Success
I want to insert a path into the loader like so:
import { Success } from '#web/components/Success'
import { loadPageContentWithPath } from '#web/utils/loadContent'
export { meta } from '#web/utils/meta'
export const loader = loadPageContentWithPath('some-path')
export default Success
However, this generates the error message on screen:
Error: Cannot initialize 'routeModules'. This normally occurs when you have server code in your client modules.
Here are the loader functions:
export const loadPageContent = async ({ params, request }) => {
const { pathname } = new URL(request.url)
...
return fetchContent()
}
export const loadPageContentWithPath = (path) => async ({ params, request }) => {
const { pathname } = new URL(request.url)
...
return fetchContent(path)
}

Related

How to use SSR with Redux in Next.js(Typescript) using next-redux-wrapper? [duplicate]

This question already has an answer here:
next-redux-wrapper TypeError: nextCallback is not a function error in wrapper.getServerSideProps
(1 answer)
Closed 1 year ago.
Using redux with SSR in Next.js(Typescript) using next-redux-wrapper, but getting error on this line
async ({ req, store })
Says, Type 'Promise' provides no match for the signature '(context: GetServerSidePropsContext<ParsedUrlQuery, PreviewData>): Promise<GetServerSidePropsResult<{ [key: string]: any; }>>
Property 'req' does not exist on type 'Store<EmptyObject & { filterReducer: never; }, any> & { dispatch: unknown; }'.
Property 'store' does not exist on type 'Store<EmptyObject & { filterReducer: never; }, any> & { dispatch: unknown; }'
Here is my SSR code:-
export const getServerSideProps: GetServerSideProps = wrapper.getServerSideProps(async ({ req, store }) => {
let { query } = req
let searchCategory = query.category?.toString().toLowerCase().replace(/ /g, "-");
const apolloClient = initializeApollo();
const response = await apolloClient.query({
query: GET_PRODUCT_BY_CATEGORY,
variables: {
numProducts: 10,
category: searchCategory
}
});
await store.dispatch(getProducts(response));
});
You're calling wrapper.getServerSideProps in a wrong way.
Try like the following:
export const getServerSideProps = wrapper.getServerSideProps(
store => async ({req, res, query}) => {
// do your stuff with store and req
}
);
If you're looking for a working demo, you can visit my old answer
This code base could help you. ("next": "10.1.3")
Try using getInitialProps instead of getServerSideProps.
This works in my case. Like code below:
Try
in _app.js
import { wrapper } from '/store';
function MyApp(props) {
const { Component, pageProps } = props;
...
return (
<Component {...pageProps} />
)
}
App.getInitialProps = async props => {
const { Component, ctx } = props;
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
//Anything returned here can be accessed by the client
return { pageProps: pageProps, store: ctx.store };
};
export default wrapper.withRedux(App);
store.js file:
const makeStore = props => {
if (!isEmpty(props)) {
return createStore(reducer, bindMiddleware([thunkMiddleware]));
} else {
const { persistStore, persistReducer } = require('redux-persist');
const persistConfig = {
key: 'root',
};
const persistedReducer = persistReducer(persistConfig, reducer); // Create a new reducer with our existing reducer
const store = createStore(
persistedReducer,
bindMiddleware([thunkMiddleware])
); // Creating the store again
store.__persistor = persistStore(store); // This creates a persistor object & push that persisted object to .__persistor, so that we can avail the persistability feature
return store;
}
};
// Export the wrapper & wrap the pages/_app.js with this wrapper only
export const wrapper = createWrapper(makeStore);
in your page:
HomePage.getInitialProps = async ctx => {
const { store, query, res } = ctx;
};

CRA Boilerplate Cannot read property 'initialLoad' of undefined In Redux -Saga & Reselect & redux-toolkit

Getting This Error When i use a useSelector hook to fetch data.
Im getting initial state undefined which cause the error.
selector.ts
import { createSelector } from '#reduxjs/toolkit';
import { RootState } from 'types';
import { initialState } from '.';
const selectSlice = (state: RootState) => state.initialLoad || initialState;
export const selectInitialLoad = createSelector([selectSlice], state => state);
index.ts
import { PayloadAction } from '#reduxjs/toolkit';
import { createSlice } from 'utils/#reduxjs/toolkit';
import { useInjectReducer, useInjectSaga } from 'utils/redux-injectors';
import { initialLoadSaga } from './saga';
import { InitialLoadState, RepoErrorType } from './types';
export const initialState: InitialLoadState = {
name: 'initial-load',
layouts: [],
loading: false,
error: null,
};
const slice = createSlice({
name: 'initialLoad',
initialState,
reducers: {
loadLayout(state) {
state.loading = true;
state.error = null;
state.layouts = [];
},
layoutLoaded(state, action: PayloadAction<[]>) {
const repos = action.payload;
state.layouts = repos;
state.loading = false;
},
layoutError(state, action: PayloadAction<string | RepoErrorType>) {
state.error = 'error';
state.loading = false;
},
},
});
export const { actions: appLayoutActions } = slice;
export const useAppLayoutSlice = () => {
useInjectReducer({ key: slice.name, reducer: slice.reducer });
useInjectSaga({ key: slice.name, saga: initialLoadSaga });
return { actions: slice.actions };
};
types.ts
/* --- STATE --- */
export interface InitialLoadState {
name: string;
loading: boolean;
error?: RepoErrorType | string | null;
layouts: [];
}
export enum RepoErrorType {
RESPONSE_ERROR = 1,
USER_NOT_FOUND = 2,
USERNAME_EMPTY = 3,
USER_HAS_NO_REPO = 4,
GITHUB_RATE_LIMIT = 5,
}
/*
If you want to use 'ContainerState' keyword everywhere in your feature folder,
instead of the 'InitialLoadState' keyword.
*/
export type ContainerState = InitialLoadState;
reducers.ts
/**
* Combine all reducers in this file and export the combined reducers.
*/
import { combineReducers } from '#reduxjs/toolkit';
import { InjectedReducersType } from 'utils/types/injector-typings';
/**
* Merges the main reducer with the router state and dynamically injected reducers
*/
export function createReducer(injectedReducers: InjectedReducersType = {}) {
// Initially we don't have any injectedReducers, so returning identity function to avoid the error
if (Object.keys(injectedReducers).length === 0) {
return state => state;
} else {
return combineReducers({
...injectedReducers,
});
}
}
this is my configuerStore.ts
/**
* Create the store with dynamic reducers
*/
import {
configureStore,
getDefaultMiddleware,
StoreEnhancer,
} from '#reduxjs/toolkit';
import { createInjectorsEnhancer } from 'redux-injectors';
import createSagaMiddleware from 'redux-saga';
import { createReducer } from './reducers';
export function configureAppStore() {
const reduxSagaMonitorOptions = {};
const sagaMiddleware = createSagaMiddleware(reduxSagaMonitorOptions);
const { run: runSaga } = sagaMiddleware;
// Create the store with saga middleware
const middlewares = [sagaMiddleware];
const enhancers = [
createInjectorsEnhancer({
createReducer,
runSaga,
}),
] as StoreEnhancer[];
const store = configureStore({
reducer: createReducer(),
middleware: [...getDefaultMiddleware(), ...middlewares],
devTools: process.env.NODE_ENV !== 'production',
enhancers,
});
return store;
}
work around
adding a condition to state
import { createSelector } from '#reduxjs/toolkit';
import { RootState } from 'types';
import { initialState } from '.';
const selectSlice = (state: RootState) => state && state.initialLoad || initialState;
export const selectInitialLoad = createSelector([selectSlice], state => state);
most of the files are of create react app boilerplate not change.
i tried the same on the cra boilerplate template without clean setup and it worked fine but after clean and setup it doesnt work how i need it too
Please define initialLoad into /src/types/RootState.ts
Example here

Redux saga failed in production

I've been trying to tackle this problem more than 2 weeks now. Everything works fine in development mode. But not in production mode. The example below are shown using Redux Saga environment (I'm still new in redux saga). But I've tried re-do it using Context API. Unfortunately the problem still persists. (below are the images showing successful process in development mode & unsuccessful process in production mode)
successful in development mode
unsuccessful in production mode
My guess it could be something to do with status code 304 Not Modified. Since the data I tried to fetch not changing, thus it will use cached data in browser. But I don't know how to setup my server so that I can handle this issue. I have read a bunch of online threads. But none were able to resolve my issue.
You may have a look at my code right now. Bear in mind that everything works just fine in development mode. From the images above you can see that I don't have problem logging in. Just fetching & getting data to be displayed in dashboard got error.
client/src/redux/actions/Dashboard.js (Action)
import { SET_ISDASHBOARD, SET_LOADING, SET_ERROR } from '../sagas/types'
// Set Loading
export const setLoading = (status) => ({
type: SET_LOADING,
payload: status
})
// Set Error
export const setError = (error) => ({
type: SET_ERROR,
payload: { error: error.status, message: error.message }
})
// Dashboard
export const isDashboard = () => ({
type: SET_ISDASHBOARD
})
client/src/redux/reducers/Dashboard.jd (Reducer)
import { SET_ERROR, SET_LOADING, SET_ISDASHBOARD, SET_DASHBOARD } from '../sagas/types'
const initialState = {
user: {
id: '',
name: '',
email: ''
},
loading: false,
error: false,
message: ''
}
const reducer = (state = initialState, action) => {
switch(action.type) {
case SET_ISDASHBOARD:
return {
...state,
loading: true
}
case SET_DASHBOARD:
return {
...state,
user: {
...state.user,
id: action.payload.id,
email: action.payload.email,
name: action.payload.name
}
}
case SET_ERROR:
return {
...state,
error: action.payload.status,
message: action.payload.message
}
case SET_LOADING:
return {
...state,
loading: action.payload
}
default:
return state
}
}
export default reducer
client/src/redux/sagas/handlers/dashboard.js (Saga handlers)
import { call, put } from 'redux-saga/effects'
import { requestGetDashboard } from '../requests/dashboard'
import { SET_LOADING, SET_ERROR, SET_DASHBOARD } from '../types'
export function* handleGetDashboard(action) {
try {
const response = yield call(requestGetDashboard)
const result = response.data.data
console.log(response); console.log(result)
// dispatch set dashboard
yield put({ type: SET_DASHBOARD, payload: { id: result.id, email: result.email, name: result.name } })
} catch(error) {
// console.log(error); console.log(error.response)
const result = error.response.data
const payload = {
status: true,
message: result.error
}
// dispatch setError
yield put({ type: SET_ERROR, payload: payload })
}
// loading to false
yield put({ type: SET_LOADING, payload: false })
}
client/src/redux/sagas/requests/dashboard.js (Saga requests)
import axios from 'axios'
/** get dashboard */
export const requestGetDashboard = () => {
return axios.get(
'/api/v1/dashboard',
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('uid')}`
}
}
)
}
client/src/redux/sagas/rootSaga.js (Root Saga)
import {
SET_ISLOGIN, SET_ISLOGOUT, SET_ISAUTH,
SET_ISDASHBOARD,
} from './types'
import { takeLatest } from 'redux-saga/effects'
import { handleClientAuth, handlePostLogin, handlePostLogout } from './handlers/auth'
import { handleGetDashboard } from './handlers/dashboard'
export function* watcherSaga() {
// auth
yield takeLatest(SET_ISLOGIN, handlePostLogin)
yield takeLatest(SET_ISLOGOUT, handlePostLogout)
yield takeLatest(SET_ISAUTH, handleClientAuth)
// dashboard
yield takeLatest(SET_ISDASHBOARD, handleGetDashboard)
}
client/src/redux/sagas/types.js (Types)
/** for AUTH */
export const SET_ISLOGIN = 'SET_ISLOGIN'
export const SET_ISLOGOUT = 'SET_ISLOGOUT'
export const SET_ISAUTH = 'SET_ISAUTH'
export const SET_AUTH = 'SET_AUTH'
export const SET_LOADING = 'SET_LOADING'
export const SET_ERROR = 'SET_ERROR'
/** for DASHBOARD */
export const SET_ISDASHBOARD = 'SET_ISDASHBOARD'
export const SET_DASHBOARD = 'SET_DASHBOARD'
Please point me to any directions that could help get closer insight to this problem.

redux-saga is not able to get payload value from dispatched action

I am trying to create a search functionality.
So the values from the search input is actually getting passed in my actions and I can see the values from redux logger. However redux saga seems not able to intercept the payload value from the action creator. When I console log it it prints undefined.
Actions
//ACTIONS
import SearchActionTypes from "./search.types";
export const SearchActionStart = (value) => ({
type: SearchActionTypes.SEARCH_START,
value
});
export const SearchActionSuccess = (items) => ({
type: SearchActionTypes.SEARCH_SUCCESS,
payload: items,
});
export const SearchActionFailure = (e) => ({
type: SearchActionTypes.SEARCH_FAILURE,
payload: e,
});
Search Component
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectFieldData } from "../../redux/search/search.selector";
import { SearchActionStart } from "../../redux/search/search.actions";
const SearchComponent = (props) => {
const { searchResults, value } = props;
useEffect(() => {}, []);
const onSearchChange = (event) => {
const { value } = event.target;
searchResults(value);
};
return (
<div>
<input
type="text"
value={value}
onChange={onSearchChange}
/>
</div>
);
};
const mapDispatchToProps = (dispatch) => ({
searchResults: (value) =>
dispatch(SearchActionStart(value)),
});
const mapStateToProps = createStructuredSelector({
searchItem: selectFieldData,
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(SearchComponent);
searchSaga
import {
put,
call,
takeLatest,
all,
} from "redux-saga/effects";
import { SearchImage } from "../../api/search-image";
import Axios from "axios";
import {
SearchActionStart,
SearchActionSuccess,
SearchActionFailure,
} from "./search.actions";
import SearchActionTypes from "./search.types";
function* fetchFieldAsync(value) {
try {
// const images = yield call(SearchImage, value);
console.log(value);
// yield put(SearchActionSuccess(value));
} catch (e) {
yield put(SearchActionFailure(e));
console.log(e);
}
}
export function* fetchFieldStart() {
yield takeLatest(
SearchActionTypes.SEARCH_START,
fetchFieldAsync
);
}
export function* searchFieldSaga() {
yield all([call(fetchFieldAsync)]);
}
rootSaga
import { call, all } from "redux-saga/effects";
import { searchFieldSaga } from "./search/search.saga";
export default function* rootSaga() {
yield all([call(searchFieldSaga)]);
}
Please have a look into this code sandbox(https://codesandbox.io/s/basic-redux-saga-49xyd?file=/index.js) ... Your code is working fine. In saga function you will get the object that has been sent from the action as the param. You can destructure it into {value} to get the search term alone as param instead of action object.
A very silly mistake.
In my searchSaga instead of exporting the watcher function fetchFieldStart function. I mistakenly exported the intermediary functions instead, which is the fetchFieldAsync function whose job is to fetch an API.
So in
searchSaga.js
instead of:
export function* searchFieldSaga() {
yield all([call(fetchFieldAsync)]);
}
It should be:
export function* searchFieldSaga() {
yield all([call(fetchFieldStart)]);
}
For anyone who might encounter undefined error in your sagas, it might be worth reviewing if your exporting correct functions.
I hope this could also help anyone who have encountered similar problem
Thanks evryone.

Calls to Dispatcher.register return `undefined`

new to Jest and having trouble with getting up and running. When calling Dispatcher.register, all I get is undefined.
I'm running Node.js 5.7.0 and Jest 0.9.2.
The following test fails:
BookedServicesStore-test.js:
jest.unmock("../BookedServicesStore");
jest.unmock("object-assign");
describe("BookedServicesStore", () => {
let BookedServicesStore;
let AppDispatcher;
beforeEach(() => {
BookedServicesStore = require("../BookedServicesStore");
AppDispatcher = require("../../dispatcher/AppDispatcher");
});
it("has a dispatch token", () => {
expect(BookedServicesStore.dispatchToken).not.toBeUndefined();
});
});
BookedServicesStore.js:
import AppDispatcher from "../dispatcher/AppDispatcher";
import { EventEmitter } from "events";
import assign from "object-assign";
const CHANGE_EVENT = "change";
const BookedServicesStore = assign({}, EventEmitter.prototype, {
emitChange() {
this.emit(CHANGE_EVENT);
},
addChangeListener(callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener(callback) {
this.removeListener(CHANGE_EVENT, callback);
}
// ...
});
BookedServicesStore.dispatchToken = AppDispatcher.register(action => {
// ...
});
module.exports = BookedServicesStore;
AppDispatcher.js:
import { Dispatcher } from "flux";
module.exports = new Dispatcher();
Not sure what's going on here. What is it that I'm missing?

Resources