running React Native app with Redux toolkit throws an error - reactjs

When i try to the run app it shows a red screen with this error in the terminal
Error: Unable to resolve module `../../../../src/assets/images` from `node_modules/#reduxjs/toolkit/dist/redux-toolkit.cjs.production.min.js`:
but It occuurs on iOS as well
The only way to make it go so far has been uninstalling react-redux. I do not have any imports in my code that point to src/assets/images as I dont have an assets/images directory to begin with.
My index.js:
import React from 'react';
import 'expo-asset';
import 'react-native-gesture-handler';
import {AppRegistry, View} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import { Provider as ReduxProvider } from 'react-redux';
import store from 'src/redux';
import React from 'react';
import 'expo-asset';
import 'react-native-gesture-handler';
import {AppRegistry, View} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import { Provider as ReduxProvider } from 'react-redux';
import store from 'src/redux';
const reduxApp = () => (
<ReduxProvider store={store}>
<App />
</ReduxProvider>
)
AppRegistry.registerComponent('main', () => reduxApp);
Redux store:
import { configureStore, getDefaultMiddleware} from '#reduxjs/toolkit';
import logger from 'redux-logger';
import { persistStore } from 'redux-persist';
import reducer from './reducers'
const middleware = [...getDefaultMiddleware(), logger]
const store = configureStore({
reducer,
middleware,
})
export const persistor = persistStore(store);
export default store;
metro.config.js:
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
};
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
[
'module-resolver',
{
alias: {
src: './src',
screens: './src/screens',
redux: './src/assets/images',
assets: './assets',
},
},
],
],
};
};

The problem is your babel.config.js file. I'm guessing that you copy and pasted some code from somewhere else without understanding what it means.
redux: './src/assets/images',
This line right here tells the compiler that the location of the redux module is ./src/assets/images. It will look for the redux source code in that folder, which doesn't exist, instead of the default location which is ./node_modules/redux.
You don't want this so delete that line.

Related

Re Exporting everything is not working as expected - issue while import in another file

I am writing the custom render for test files in react project which is using react testing library so that i can avoid the boiler plate for every test file where i have wrapped it with the Tag.
So in the custom render file test-util.tsx I am exporting everything from #testing-library/react so that I can import my custom render function and all the other React Testing Library functionality (fireEvent , screen etc.) from the same place.
but while doing so i can not import other RTL functions like fireEvent, screen, waitFor etc.
Below is my code :
test-utils.tsx:
import React, {FC, ReactElement} from 'react';
import {render} from '#testing-library/react';
import {Provider} from 'react-redux';
import {BrowserRouter as Router} from 'react-router-dom';
import configureStore from 'redux-mock-store';
const mockStore = configureStore([]);
const customRender = (
ui: ReactElement,
{initialState = {}, store = mockStore(initialState), ...renderOptions} = {}
) => {
const ProviderWrapper: FC = ({children}) => {
return (
<Router>
<Provider store={store}>{children}</Provider>
</Router>
);
};
return render(ui, {wrapper: ProviderWrapper, ...renderOptions});
};
export * from '#testing-library/react';
export {customRender as renderWithProviders};
test file -- abc.test.tsx
import {renderWithProviders, screen, fireEvent, waitFor} from 'test-utils';
errors :
has no exported member 'fireEvent'
has no exported member 'waitFor'
to avoid the relative import i have done below config set up:
jest.config.json :
test-utils is under src/utils/test-utils
module.exports = {
...
moduleDirectories: ['src', 'node_modules', '<rootDir>/src/utils'],
...
}
**tsconfig.json: **
"compilerOptions" : {
...,
"baseUrl": "./src",
"paths": {
"^/*": ["../*"],
"#/*": ["*"],
"test-utils": ["./utils/test-utils"]
}
...
}

How to pass a const variable from one component to another react

Hello I am trying to add Apollo to my react app and in the documentation it says to wrap you app in the <ApolloProvider client={client}> tag and pass client in as a variable like so:
import React from 'react';
import ReactDOM from 'react-dom';
import PageLayout from './components/page-layout'
import CreateApolloClient from './apollo-settings'
import { ApolloProvider } from '#apollo/react-hooks';
import ApolloClient from 'apollo-boost';
import {BrowserRouter} from 'react-router-dom';
const client = new ApolloClient({
uri: 'http://localhost/headless-cms/admin/',
fetchOptions: {
mode: 'no-cors',
},
});
ReactDOM.render(<ApolloProvider client={client}><BrowserRouter><PageLayout /></BrowserRouter></ApolloProvider>, document.getElementById('site-wrapper'));
However I want to remove the const client from the index.js page and move it into another template just to keep things organised like so:
import React from 'react';
import { ApolloProvider } from '#apollo/react-hooks';
import ApolloClient from 'apollo-boost';
const CreateApolloClient = () => {
const client = new ApolloClient({
uri: 'http://localhost/headless-cms/admin/',
fetchOptions: {
mode: 'no-cors',
},
});
}
export default CreateApolloClient;
What I am struggling with is when importing CreateApolloClient into the index.js page how do I then access the const client and pass it into the <ApolloProvider client={client}>
Thank you for any help in advanced
You should return the apollo client instance in your function and export the createApolloClient.
import { ApolloProvider } from '#apollo/react-hooks';
import ApolloClient from 'apollo-boost';
export const createApolloClient = () => {
return new ApolloClient({
uri: 'http://localhost/headless-cms/admin/',
fetchOptions: {
mode: 'no-cors',
},
});
}
export default CreateApolloClient;
import React from 'react';
import ReactDOM from 'react-dom';
import PageLayout from './components/page-layout'
import {createApolloClient} from './apollo-settings'
import {BrowserRouter} from 'react-router-dom';
import { ApolloProvider } from '#apollo/react-hooks';
const client = createApolloClient();
ReactDOM.render(<ApolloProvider client={client}><BrowserRouter><PageLayout /></BrowserRouter></ApolloProvider>, document.getElementById('site-wrapper'));

How to handle two configureStore files for Redux in TypeScript (multiple module.exports)?

I'm building a React Native app with TypeScript using Redux for my state.
I like using two seperate files for configureStore. In JS This looks like this:
configureStore.dev.js:
import { applyMiddleware, createStore } from "redux";
import logger from "redux-logger";
import reducers from "../reducers";
const configureStore = () => {
const store = createStore(reducers, applyMiddleware(logger));
return store;
};
export default configureStore;
configureStore.prod.js:
import { createStore } from "redux";
import reducers from "../reducers";
const configureStore = () => {
const store = createStore(reducers);
return store;
};
export default configureStore;
configureStore.js:
import Config from "react-native-config";
if (Config.REACT_ENVIRONMENT === "staging") {
module.exports = require("./configureStore.dev");
} else {
// tslint:disable-next-line no-var-requires
module.exports = require("./configureStore.prod");
}
And then within App.js:
import React, { Component } from "react";
import Orientation from "react-native-orientation";
import { Provider } from "react-redux";
import Navigator from "./navigation/Navigator";
import configureStore from "./redux/store/configureStore";
export const store = configureStore();
export default class App extends Component {
componentDidMount = () => {
Orientation.lockToPortrait();
};
render() {
return (
<Provider store={store}>
<Navigator />;
</Provider>
);
}
}
The problem now with TypeScript is that - after converting these files to .ts and .tsx - this code throws linting errors (and it furthermore blocks all Jest unit tests from running).
The lines where modules.exports exports the respective file depending on environment variables throws the error:
[tslint] require statement not part of an import statement (no-var-requires)
And in App.tsx the import of configureStore throws:
[ts] Module '"/Users/jan/Documents/FullStackFounders/PainButton/painbutton/app/redux/store/configureStore"' has no default export.
How would one handle this case in TypeScript?
The only solution I could come up with was only using one file and using a lot of if's for all the Dev only configs. But that doesn't seem clean to me.
It seems you are mixing import / export and require / module.exports syntax.
Try to use dynamic import expressions.
configureStore.js
export default Config.REACT_ENVIRONMENT === "staging" ? import("./configureStore.dev") : import("./configureStore.prod");
main render file
import configure from "./configureStore.js";
configure.then(configFunc => {
const store = configFunc();
ReactDOM.render(<App store={store} />, document.querySelector("#root"));
})
Pass the store as a prop to the <App /> Component.
I hope it will help.

Helmet errors with renderStatic

I'm trying to setup Helmet npm using SSR within my meteor application and I'm getting the error, Error running template: TypeError: Cannot read property 'renderStatic' of undefined at sink. I'm new to using SSR so I'm not following what I'm missing here. Very nooooob question.
Path: server/main.js
import React from "react";
import PropTypes from 'prop-types';
import { onPageLoad } from "meteor/server-render";
import { renderToNodeStream } from "react-dom/server";
import { ServerStyleSheet } from "styled-components"
import { Helmet } from 'react-helmet';
import App from "/imports/server/app/App";
onPageLoad(sink => {
const sheet = new ServerStyleSheet();
const appJSX = sheet.collectStyles(
<App location={sink.request.url} />
);
App.propTypes = {
location: PropTypes.object,
};
const htmlStream = sheet.interleaveWithNodeStream(
renderToNodeStream(appJSX)
);
sink.renderIntoElementById("react-root-app", htmlStream);
const helmet = Helmet.renderStatic();
sink.appendToHead(helmet.meta.toString());
sink.appendToHead(helmet.title.toString());
});
Since Helmet is default export you need to import it like
import Helmet from 'react-helmet';
But not
import { Helmet } from 'react-helmet';
However, the latest version does not have a default import.
You must import it like this.
import { Helmet } from 'react-helmet';
This is as per the version
"react-helmet": "^6.0.0",

Browser history needs a DOM

There are already questions around this topic with solutions pointing to memoryHistory on server. However, I did that and the problem still remains to be on store.js which is inside client folder. Although I am not using this client/store.js it still gives me same error as the subject.
So my guess is there is something wrong in the way I am wrapping up my component on server or client side.
I am working on already loaded project stack - redux, react-redux, react-router-redux, redux-thunk, history etc... and these are honestly daunting for me to make an addition for a setup for SSR -server side rendering (my basic motive)
I will share my structure and important files which are involved in this exercise !
Let's welcome the server first.
server/bootstrap.js
require('ignore-styles');
require('babel-register')({
ignore: [ /(node_modules)/ ],
presets: ['es2015', 'react-app']
});
require('./index');
server/index.js
import express from 'express';
import serverRenderer from './middleware/renderer';
const PORT = 3000;
const path = require('path');
const app = express();
const router = express.Router();
// root (/) should always serve our server rendered page
router.use('^/$', serverRenderer);
// other static resources should just be served as they are
router.use(express.static(
path.resolve(__dirname, '..', 'build'),
{ maxAge: '30d' },
));
router.use('*', serverRenderer);
// tell the app to use the above rules
app.use(router);
// start the app
app.listen(PORT, (error) => {
if (error) {
return console.log('something bad happened', error);
}
console.log("listening on " + PORT + "...");
});
server/middleware/renderer.js
import React from 'react'
import ReactDOMServer from 'react-dom/server';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import store from '../../src/store';
import {createMemoryHistory } from 'history';
import { StaticRouter } from 'react-router'
// import our main App component
import App from '../../src/index';
const path = require("path");
const fs = require("fs");
const history = createMemoryHistory({
initialEntries: ['/', '/next', '/last'],
initialIndex: 0
})
export default (req, res, next) => {
const filePath = path.resolve(__dirname, '..', '..', 'build', 'index.html');
fs.readFile(filePath, 'utf8', (err, htmlData) => {
if (err) {
console.error('err', err);
return res.status(404).end()
}
const html = ReactDOMServer.renderToString(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>
);
return res.send(
htmlData.replace(
'<div id="root"></div>',
`<div id="root">${html}</div>`
)
);
});
}
My src folder structure will be
components
containers
app
index.js
styles.js
index.js
store.js
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import { StaticRouter } from 'react-router'
import './index.css';
import store, { history } from './store';
import App from './containers/app';
const target = document.querySelector('#root');
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
target
);
The tough nut to understand
src/store.js
import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk';
import createHistory from 'history/createBrowserHistory';
import rootReducer from './reducers';
export const history = createHistory();
const initialState = {};
const enhancers = [];
const middleware = [thunk, routerMiddleware(history)];
if (process.env.NODE_ENV === 'development') {
const devToolsExtension = window.devToolsExtension;
if (typeof devToolsExtension === 'function') {
enhancers.push(devToolsExtension());
}
}
const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers);
const store = createStore(rootReducer, initialState, composedEnhancers);
export default store;
on running node server/bootstrap.js, it give me an error
Invariant Violation: Browser history needs a DOM and this error generates in store.js
If someone could please let me know by the code shared what and where I am doing wrong to my current create-react-app for SSR!
I was loading the App twice. Once in client and other in server.
I rendered in server alone with the same setup (Provider and connected router) and importantly changed the createBrowserHistory to createMemoryHistory and it worked.

Resources