React relay injectNetworkLayer is not a function - reactjs

I am following the tutorial from lynda: "Building and Deploying a Full-Stack React Application", in the chapter "Injecting the Relay Network Layer". there is in index.js, an attempt to set up a network layer, and the program compiles successfully but I'm receiving the following error in the browser:
TypeError: __WEBPACK_IMPORTED_MODULE_4_react_relay___default.a.injectNetworkLayer is not a function
index.js file is:
import React from 'react'
import ReactDOM from 'react-dom'
import {Router, browserHistory, applyRouterMiddleware} from 'react-router'
import Routes from './routes'
import Relay from 'react-relay'
import useRelay from 'react-router-relay'
import {RelayNetworkLayer, urlMiddleware} from 'react-relay-network-layer'
import {relayApi} from './config/endpoints'
import auth from './utils/auth'
const createHeaders = () => {
let idToken = auth.getToken()
if (idToken) {
return {
'Authorization': `Bearer ${idToken}`
}
} else {
return {}
}
}
Relay.injectNetworkLayer(
new RelayNetworkLayer([
urlMiddleware({url: (req) => relayApi,}),
next => req => {
req.headers = {
...req.headers,
...createHeaders()
}
return next(req)
},
],{disableBatchQuery: true})
)
ReactDOM.render(
<Router
environment={Relay.Store}
render={applyRouterMiddleware(useRelay)}
history={browserHistory}
routes={Routes}
/>,
document.getElementById('root')
)

It might be easier to just use the classic version of react-relay.
import Relay from 'react-relay/classic'

Duplicate question.
Found Chris Mazzouchi's answer helpful, though I had to uninstall and re-install the following specific versions to get it working:
yarn remove react-relay react-relay-network-layer react-router-relay
yarn add react-relay#0.10.0 react-relay-network-layer#1.3.9 react-router-relay#0.13.5

Related

Error message with: Web3 + create-react-app + webpack 5

I am writing the frontend for a Dapp.
I have the script /src/config/index.js
import Web3 from 'web3';
const getLibrary = (provider) => {
return new Web3(provider);
};
export { getLibrary };
And the /src/index.js where I am trying to import getLibrary:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { HashRouter } from 'react-router-dom';
import { ChakraProvider } from '#chakra-ui/react';
import { Web3ReactProvider } from '#web3-react/core';
import { getLibrary } from './config/web3';
ReactDOM.render(
<React.StrictMode>
<HashRouter>
<ChakraProvider>
<Web3ReactProvider getLibrary={getLibrary}>
<App />
</Web3ReactProvider>
</ChakraProvider>
</HashRouter>
</React.StrictMode>,
document.getElementById('root')
);
But, I have the error
The line responsible for the error is:
import { getLibrary } from './config/web3';
I used create-react-app to build the project.
I have try several ideas but nothing is working for me... any help, please?
I had the same problem when using web3 with react and webpack 5. This helped me solve it. I followed option #1 as I couldn't get the other option to work (my main confusion being where to keep webpack.config.js since I had kept it at the root and it was not being picked up).
For anyone looking to resolve this still (2022-08-30), I recommend reading this article:
https://alchemy.com/blog/how-to-polyfill-node-core-modules-in-webpack-5
It will be different in regards to your dependencies but it helped resolve my issues. It basically adds support back in by rerouting requests to dependencies using the react-app-rewired package.

Redux TS Generic type 'Dispatch<S>' requires 1 type argument(s)

Trying to setup a project with typescript and redux.
I am getting this error
Generic type 'Dispatch<S>' requires 1 type argument(s).
here is my store.ts
import { connectRouter, routerMiddleware } from 'connected-react-router'
import { applyMiddleware, compose, createStore } from 'redux'
import { createLogger } from 'redux-logger'
import ReduxThunk from 'redux-thunk'
import { createBrowserHistory } from 'history'
import reducers from './reducers'
import { composeWithDevTools } from 'redux-devtools-extension'
export const history = createBrowserHistory()
const composeEnhancers = composeWithDevTools({
// Specify name here, actionsBlacklist, actionsCreators and other options if needed
})
const logger = createLogger()
const middleware = [ReduxThunk, logger]
const Store = createStore(connectRouter(history)(reducers), {}, composeEnhancers(applyMiddleware(...middleware, routerMiddleware(history))))
export default Store
here is root reducer
import { combineReducers } from 'redux'
import { ActionType } from 'typesafe-actions'
import * as actions from '../actions'
export interface IState {
test: string
}
export type Actions = ActionType<typeof actions>
export default combineReducers<IState, Actions>({
test: () => 'hey'
})
and here are some dummy actions
import { action } from 'typesafe-actions'
export const toggle = (id: string) => action('TOGGLE', id)
// (id: string) => { type: 'todos/TOGGLE'; payload: string; }
finally here is index.ts
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import App from './App'
import './index.scss'
import registerServiceWorker from './registerServiceWorker'
import store, { history } from './store'
import { Provider } from 'react-redux'
import { Route, Switch } from 'react-router' // react-router v4
import { ConnectedRouter } from 'connected-react-router'
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}> { /* place ConnectedRouter under Provider */}
<div> { /* your usual react-router v4 routing */}
<Switch>
<Route exact path="/" render={() => (<div>Match</div>)} />
<Route render={() => (<div>Miss</div>)} />
</Switch>
</div>
</ConnectedRouter>
</Provider>,
document.getElementById('root') as HTMLElement
)
registerServiceWorker()
Here seems to be a similar issue without solution yet
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/9611
But I am new to typescript so might be missing something basic
It looks to me like you are indeed facing the same issue you linked. While we wait and see if 7mllm7's pull request is merged, you can use his modified version of the react-redux types. I'd recommend the following approach:
git clone --depth=1 https://github.com/7mllm7/DefinitelyTyped
Copy the types/react-redux folder into your project (suppose for example you copy it to a folder named react-redux.fixed).
Edit react-redux.fixed/package.json to replace "private": "true" with "name": "#types/react-redux".
In your package.json, specify the version of #types/react-redux as ./react-redux.fixed.
Run npm install. npm will make a symlink from node_modules/#types/react-redux to react-redux.fixed.
Compared to just editing the file in node_modules/#types/react-redux, this way npm knows you are using a modified version of the package and won't overwrite it. (This process deserves to be widely known; I'll find a better place to document it if I have time.)
I solved this by downgrading to Redux 3.7. It has proper typings (There still aren't typings for Redux 4.0). There are some Github issues where they discuss about it (here and here).

#withRouter Unexpected Token Error

Seems every time I have to setup React Router in a new project I run into something new possibly by version changes.
I am using reactjs and mobx state tree(though at this point have not used anything of it).
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import HomeComponent from './HomeComponent.js';
import {withRouter, Route} from 'react-router'
#withRouter
export default class App extends Component {
render() {
return (
<Route exact path='/' component={HomeComponent}/>
);
}
}
export default App;
When I run it I get
ERROR in ./src/components/App.js
Module build failed: SyntaxError /components/App.js: Unexpected token (6:0)
I also get some warning as well
Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.
Edit
Per the comment from "Artem Mirchenko"
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'mobx-react';
import { useStrict } from 'mobx';
import createBrowserHistory from 'history/createBrowserHistory';
import {syncHistoryWithStore } from 'mobx-react-router';
import { Router } from 'react-router'
import AppContainer from './components/App';
const browserHistory = createBrowserHistory();
import stores from '../src/stores/Stores';
const history = syncHistoryWithStore(browserHistory, stores.routingStore);
ReactDOM.render(
<Provider {... stores}>
<Router history={history}>
<AppContainer />
</Router>
</Provider>,
document.getElementById('app')
);
import {RouterStore} from 'mobx-react-router';
const routingStore = new RouterStore();
const stores = {
routingStore
}
export default stores;
You need to install babel plugin transform-decorators-legacy.
Via yarn:
yard add --dev transform-decorators-legacy
Vie npm:
npm install --save-dev transform-decorators-legacy
And add in to plugins ket in you babel options:
{
// pressets ....
"plugins": ["transform-decorators-legacy"]
}

How to configure a basename in React Router 3.x

I have an app running at a nested url as opposed to the root. Lets say example.com/app.
I read here that in react router 2.x you could configure basenames.
How can this be done in react router 3.x?
FYI I am also using the react-router-redux package.
This functionality does not exist in React Router anymore. I went through a similar problem and found this fix.
Step 1: Install History (3.0.0)
npm install --save history#3.0.0
Step 2: Import { useBasename } from history in your router file (the file with <Router>):
import { useBasename } from 'history'
Step 3: Modify your <Router> like the below example:
<Router history={ useBasename(() => browserHistory)({ basename: '/app' }) }>
I think the section on configuring histories in the React Router docs is what you're looking for:
https://github.com/ReactTraining/react-router/blob/v3/docs/guides/Histories.md#customize-your-history-further
Here's a full example integrating with react-router-redux (with some unnecessary info excluded):
import React from 'react';
import ReactDOM from 'react-dom';
import createBrowserHistory from 'history/lib/createBrowserHistory';
import { useRouterHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import Root from './containers/Root';
import configureStore from './store/configureStore';
const historyConfig = { basename: '/some-basename' };
const browserHistory = useRouterHistory(createBrowserHistory)(historyConfig);
const store = configureStore({ initialState, browserHistory });
const history = syncHistoryWithStore(browserHistory, store, {
selectLocationState: (state) => state.router,
});
ReactDOM.render(
<Root history={history} store={store} />,
document.getElementById('root')
);

Redux Hot Reload Warning on changes

I get the following warning when I try to update any of my react components...
Provider does not support changing store on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions.
As far as I can tell, my code looks like the instructions, but I still get the warning.
client.js
'use strict'
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { Router, browserHistory } from 'react-router';
import createStore from '../shared/store/createStore';
import routes from '../shared/routes';
const store = createStore(window.__app_data);
const history = browserHistory;
if (window.__isProduction === false) {
window.React = React; // Enable debugger
}
if (module.hot) {
module.hot.accept();
}
render (
<Provider store={store}>
<Router history={history} routes={routes} />
</Provider>,
document.getElementById('content')
)
configureStore.js
'use strict';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducers from '../reducers';
import { selectSubreddit, fetchPosts } from '../actions'
export default function createReduxStore(initialState = {}) {
const store = createStore(reducers, initialState, applyMiddleware(thunk));
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers', () => {
const nextReducer = require('../reducers').default;
store.replaceReducer(nextReducer);
});
}
return store;
};
Server.js
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import webpackConfig from '../../webpack.config.dev';
let compiler = webpack(webpackConfig);
app.use(webpackDevMiddleware(compiler, {
hot: true,
noInfo: true,
publicPath: webpackConfig.output.publicPath
}));
app.use(webpackHotMiddleware(compiler));
Is there something I'm missing? Here is a link to the full Github Repo if you want to see the full src.
[Edited] Added server.js and github link.
Found the answer. There were multiple changes needed.
Remove module.hot code from client.js (Hot reloading that file caused Redux and React-Router warnings.
Create an index file for my React page components to export from.
Add module.hot code to newly created index file.
Change all React components to classes. const Page = () => () doesn't re-render with hot reloading.
After making those changes, everything started to work properly and I get no more warnings :-)

Resources