Issue with imports in React/Redux application - reactjs

I'm using a Rails-style organization for a React/Redux project but I'm having an import issue that I can't figure out.
I have a constants directory with a module index (index.js) that looks like this:
import * as types from './ActionTypes';
export default types;
(All my action creators are in ./ActionTypes.)
I then have an actions/index.js file where I import all the constants I need for my actions (I've included just one of the action creators for brevity):
import * as c from './../constants';
...
export const toggleForm = () => ({
type: c.TOGGLE_FORM
});
I've thoroughly tested all reducers and action creators - and all tests pass without import issues.
However, in my React app, which was working before I refactored to use action creators, I get the following issue and my project won't compile: Attempted import error: 'TOGGLE_FORM' is not exported from './../constants' (imported as 'c').
If I specify that constants should be imported into actions/index.js with import * as c from './../constants/ActionTypes.js'; (bypassing my constant's directory's module index) - the React application compiles correctly but the tests for my action creators breaks.
What am I missing here?

Delete
import * as types from './ActionTypes';
export default types;
and instead export all your actions as const like so
// user authentication actions
export const SET_USER = 'SET_USER'
export const CLEAR_USER = 'CLEAR_USER'
export const VERIFY_USER = 'VERIFY_USER'
it should work now

Related

react: export {ModuleName} was not found (module has no exports)

React CRA sometimes can not find react tsx modules.
React version: 18.2.0
Node version: 19.2.0
I've tried to lower Node version. I've tried change export from export * from './ModuleName to export {ModuleName} from './ModuleName and change import from something like import {ModuleName} from ./ModuleName to import {ModuleName} from ./ModuleName/ModuleName. Sometime it helps, sometimes not.
All components written in next pattern:
type ModuleNameProps = {/* some props *.};
export const ModuleName = ({/* props */}: ModuleNameProps): JSX.Element => { /* Component body */};
export * from './ModuleName';
P.S. Application still works with such errors and other developers on a project don't have such errors
P.P.S. Such errors seem to occur only when path to component contains repetitions. For example: './ComponentName/ComponentName/ComponentName.tsx'

Typescript npm library can't export Redux store please advice

I use the Notistack library and forked it and then using VSCode to try to add a Redux store in the library that I want to expose to Apps.
I'm not so good with Typescript. I have some trouble hehe.
What I want to do is that when the app is using Notistack to show a snack message. I want to use Redux to update the message in real time, like a file up/download progress showing on the snack. It's here Notistack new Redux store(that i create here) come into play. I want Notistack to expose the Redux store to the app so the app can send redux dispatch into to Notistack Redux Store. and showing dispatched message in the Notistack SnackbarItem.tsx
(hope you understand)
When I compile in VSCode I get this error in my app:
Failed to compile.
./src/redux/root-reducer.js
Attempted import error: 'notistack' does not contain a default export (imported as 'NotisReducer').
My root-reducer in the App look like this:
import { combineReducers } from 'redux';
import NotisReducer from 'notistack';
import snackReducer from './snackbar/snack.reducer';
const rootReducer = combineReducers({
snack: snackReducer,
NotisReducer,
});
export default rootReducer;
As you see I import Notistack's NotisReducer and I think I have implemented that.
(I have used NPM link to add locally forked Notistack library into my app)
Now it looks like this here is Notistack's indext.js file where I expose Redux store as NotisReducer:
What I did in Notistack was I added a to index.d.ts:
I define the type store like this:
import * as React from 'react';
import { SnackbarClassKey } from '#material-ui/core/Snackbar';
import { ClickAwayListenerProps } from '#material-ui/core/ClickAwayListener';
import { TransitionProps } from '#material-ui/core/transitions/transition';
import { StandardProps } from '#material-ui/core';
import store from './Redux/store'; // MY STORE
...
...
export type store = store; // EXPORT IT
I'm not sure if this is correct as I could not set breakpoint in npm linked Notistack. Maybe it's to many problem now that must be fixed first.
In the file
SnackbarProvider.tsx
I did like this, importing the store type from index.d.ts):
import {
SnackbarProviderProps,
SnackbarKey,
SnackbarMessage,
OptionsObject,
RequiredBy,
ProviderContext,
TransitionHandlerProps,
store, // STORE
} from ".";
import createChainedFunction from "./utils/createChainedFunction";
export { store }; // EXPOSING IT
In the file
NotisReducer.js
I import the store to be sent to indext.js above
But as you saw above I get compiler error store is not exported.
Attempted import error: 'notistack' does not contain a default ex (imported as 'NotisReducer').
please advice :))

When I try to export action with redux I get an error that says "does not contain a default export"

I am trying to learn redux and I have a file with an action in it.
export const changeTitle = () => {
return {
type: 'CHANGE_PROJECT_TITLE',
};
};
Then I am trying to import it in a component.
import changeTitle from '../actions/index.js';
This works if I use export default in the action file but then I can only have one action.
export default changeTitle;
I am trying to figure out why it will not work without the the export default.
When I try without the export default I get an error that says : "Attempted import error: '../actions/index.js' does not contain a default export (imported as 'changeTitle')." I believe I have seen examples that work without the default export so they can use multiple actions.
in your case just change
import changeTitle from '../actions/index.js';
to
import { changeTitle } from '../actions/index.js';
and you can omit index.js name in import, it's default file for import
import { changeTitle } from '../actions';
more information about export you can find on mdn

Importing redux action makes other actions undefined

This is one of the strangest things I have ever seen. It makes absolutely no sense to me. The short version is I have a Redux action creator function. If I import this function into this one particular component file, it makes every function imported from its file undefined.
So, let's start with the file filterInputModal.actions.js. This contains my Redux action functions, created using redux-starter-kit:
export const showAddCategoryModal = createAction('showAddCategoryModal');
That is the function I've been working with. Now, this function has long since been imported into my ManageVideoFilters.js component:
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { showAddCategoryModal } from 'store/filterInputModal/filterInputModal.actions';
const ManageVideoFilters = (props) => {
/* Component logic */
};
/* PropTypes and mapStateToProps */
const mapDispatchToProps = (dispatch) => bindActionCreators({
showAddCategoryModal: () => showAddCategoryModal() // Done this way to avoid passing in a payload, since certain default event payloads cause Redux to print console errors
});
export default connect(mapStateToProps, mapDispatchToProps)(ManageVideoFilters);
So far so good. Before we go and break everything, let's take a look at my filterInputModal.reducer.js Redux reducer, also created using Redux Starter Kit:
import { createReducer } from 'redux-starter-kit';
import { showAddCategoryModal } from './filterInputModal.actions';
const initialState = {}; // The initial state for the reducer goes here
const handleShowAddCategoryModal = (state) => {
/* handle updating the state */
return state;
};
const actionMap = {
[showAddCategoryModal]: handleShowAddCategoryModal
};
export default createReducer(initialState, actionMap);
The action map uses the action creator functions toString() as the key, and then I provide my own functions to handle updating the state. Again, at this point, everything is perfect. We will come back to the reducer in a sec, first let's break things.
Now we're going to my VideFileEdit.js component. If we add the following line to this component, everything breaks:
import { showAddCategoryModal } from 'store/filterInputModal/filterInputModal.actions';
So, how does it break?
The import of the showAddCategoryModal function in filterInputModal.reducer.js now is undefined.
Because the reducer is using the functions as the keys to handle actions, the reducer is no longer able to handle the action properly and update the state.
It gets weirder though. Here are some of the weird behaviors I'm seeing.
If I import this action into any other component, everything is fine. The import in the reducer is unchanged.
The import of the function in both ManageVideoFilters.js and VideoFileEdit.js is fine.
So, what can I try next? This is really strange and doesn't make any sense to me. I've never seen this before.
As the commenter said, the problem was recursive imports. My filterInputModal.reducer.js exported some constants, which were imported into my filterInputModal.actions.js. The actions from filterInputModal.actions.js were then imported into filterInputModal.reducer.js. Hence the recursive import.
I moved the constants into a new file, filterInputModal.constants.js, and viola, problem solved.

When using ES6, how can an imported function be undefined in one file, and not in another?

I'm using babel / ES6 with webpack. I'm importing the same 'actions' file - which exports a bunch functions - in two different places. At one place it returns a module, the other undefined:
actions.js
export function test() { ... }
export function test2() { ... }
App.js
import actions from './actions'
class App extends React.Component { ... }
console.log(actions); //<-------- Object{test:function,test2:function)
export default connect((state) => { ... },actions)(App);
edit
the reason App.js worked was because it was actually using import * as actions as sugested below, I just retyped it wrong in the example
NestedComponent.js
import actions from './actions'
class NestedComponent extends OtherComponent { ... }
console.log(actions); //<-------- logs undefined
export default connect((state) => { ... },actions)(NestedComponent);
Is this related to the order in which webpack defines the modules/files?
I ran into a similar issue, caused by circular dependencies. Tried to import a constant in file 'A' from file 'B' which in turn tried to import from file 'A'.
This shouldn't work in either case because you are importing the wrong values. import foo from '...' imports the default export of the module, but you don't have a default export, you only have named exports.
What you should use is
import {test, test2} from './actions';
// or
import * as actions from './actions';
Another common case where this happens is if you're testing with Jest and auto-mocking behavior is enabled. Much grief, such gotcha.

Resources