When using custom hooks with jest and enzymne I get this error 'TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined'
Tried various things but nothing seems to work. Please help
import React, { useEffect, useState, Fragment } from 'react';
/* Utils */
import { useSystemContext } from '../../../utils/Context/SystemContextProvider';
/* Components */
import MenuStructure from './MenuStructure';
const Menu = () => {
const [{ siteData }] = useSystemContext();
const [open, setOpen] = React.useState(false);
const openMenu = () => {
setOpen(!open);
};
const componentProps = {
menuItems: siteData,
openMenu: openMenu,
open: open
};
return (
<MenuStructure {...componentProps} />
)
};
export default Menu;
Test
import { shallow, mount } from 'enzyme';
import Menu from '.';
import { testUseState } from '../../../utils/TestUtils';
describe('<Menu />', () => {
let wrapper;
it('calls setCount with 0', () => {
wrapper = mount(<Menu />);
});
});
Error
TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
9 | import MenuStructure from './MenuStructure';
10 |
> 11 | const Menu = () => {
| ^
12 | const [{ siteData }] = useSystemContext();
13
added useSystemContext as requested
import React, { createContext, useContext, useReducer } from 'react';
export const SystemContext = createContext();
export const SystemContextProvider = ({ reducer, initialState, children }) => (
<SystemContext.Provider value={useReducer(reducer, initialState)}>
{children}
</SystemContext.Provider>
);
export const useSystemContext = () => useContext(SystemContext);
This is works fine in the site when running
Related
I have a question about userContext in react with typescript.
First I define it in RubroContext.tsx
import { createContext, useContext } from "react";
import { RubroType1, RubroType2 } from "../Interfaces/interfaces";
export const RubroContext1 = createContext <Partial<RubroType1>>({})
export const RubroContext2 = createContext <Partial<RubroType2>>({})
export const useRubroContext1 = () => useContext(RubroContext1);
export const useRubroContext2 = () => useContext(RubroContext2);
this is interfaces.tsx
export type RubroType1 = {
rubrosItem1 : itemRubro;
setItemRubro1: Dispatch<SetStateAction<itemRubro >>;
}
export type RubroType2 = {
rubrosItem2 : itemRubro;
setItemRubro2 : Dispatch<SetStateAction<itemRubro >>;
}
and this is how I implement it in the components
const CompletarRubros = (props:{setIsReg:any,email:any, clientType:any}) => {
const {rubrosItem1,setItemRubro1} = useRubroContext1 ()
const {rubrosItem2,setItemRubro2} = useRubroContext2 ()
const rubro = useRef ("first")
const radius = useRef (1)
const description = useRef ("test")
useEffect(() => {
setItemRubro1!({
rubro:rubro.current,
radius:String(radius),
description:descripcion.current,
calificacion:0,
})
}, []);
//...........
}
The problem is that the code is not updated. When I want to access rubrosItem1 in other components, the information that should have been saved in the useEffect is not there. I am doing something wrong?
for example in another component
const Test= () => {
const {rubrosItem1,setItemRubro1} = useRubroContext1 ()
useEffect(() => {
console.log(rubrosItem1.rubro)
// it does not show anything
}, []);
}
You should create a RubroContext1Provider component and declare the context value as its local state. So that the children of the RubroContext1Provider component and share the context value(stored in its state).
E.g.
RubroContext.tsx:
import {
createContext,
Dispatch,
SetStateAction,
useContext,
useState,
} from 'react';
import * as React from 'react';
type itemRubro = any;
export type RubroType1 = {
rubrosItem1: itemRubro;
setItemRubro1: Dispatch<SetStateAction<itemRubro>>;
};
export type RubroType2 = {
rubrosItem2: itemRubro;
setItemRubro2: Dispatch<SetStateAction<itemRubro>>;
};
export const RubroContext1 = createContext<Partial<RubroType1>>({});
export const RubroContext2 = createContext<Partial<RubroType2>>({});
export const useRubroContext1 = () => useContext(RubroContext1);
export const useRubroContext2 = () => useContext(RubroContext2);
export const RubroContext1Provider = ({ children }) => {
const [value, setValue] = useState();
return (
<RubroContext1.Provider
value={{
rubrosItem1: value,
setItemRubro1: setValue,
}}
>
{children}
</RubroContext1.Provider>
);
};
CompletarRubros.tsx:
import { useEffect, useRef } from 'react';
import { useRubroContext1 } from './RubroContext';
export const CompletarRubros = () => {
const { rubrosItem1, setItemRubro1 } = useRubroContext1();
const rubro = useRef('first');
const radius = useRef(1);
const description = useRef('test');
useEffect(() => {
setItemRubro1({
rubro: rubro.current,
radius: String(radius),
description: description.current,
calificacion: 0,
});
}, []);
return null;
};
Test.tsx:
import { useRubroContext1 } from './RubroContext';
export const Test = () => {
const { rubrosItem1 } = useRubroContext1();
console.log('[Test]:', rubrosItem1?.rubro);
return null;
};
App.tsx:
import * as React from 'react';
import { CompletarRubros } from './CompletarRubros';
import { RubroContext1Provider } from './RubroContext';
import './style.css';
import { Test } from './Test';
export default function App() {
return (
<div>
<RubroContext1Provider>
<CompletarRubros />
<Test />
</RubroContext1Provider>
</div>
);
}
The console logs:
[Test]:undefined
[Test]:undefined
[Test]:first
[Test]:first
stackblitz
I have this problem, can anyone help me?
TypeError: customers.map is not a function.
I've always used it that way and I've never had any problems.
Its about data integration.
Basically is that, please anyone can help me?
import React, { useState, useEffect } from "react";
import { List, Card } from "antd";
import { data } from "../../../mocks/customers";
import { DeleteCustomerButton } from "#components/atoms/DeleteCustomerButton";
import { CustomersEditButton } from "#components/atoms/CustomersEditButton";
import { useContext } from "../../../contexts/context";
const { Meta } = Card;
const CustomersCardList: React.FC = () => {
const customers: any = useContext();
return (
<div>
{customers.map((customer, key) => { })}</div>)
}
//context.tsx
import * as React from 'react';
import axios from 'axios';
export const AccountContext = React.createContext({});
export const useContext = () => React.useContext(AccountContext);
interface AccounterContextProviderProps {
value: any
};
export const AccounterContextProvider: React.FC<AccounterContextProviderProps> = ({ children, value }) => {
const [customers, setCustomers] = React.useState<any>([]);
React.useEffect(() => {
const getCustomers = async () => {
const result = await axios.get("http://localhost:3333/customers");
setCustomers(result.data);
}
getCustomers();
}, []);
console.log(customers);
return (
<AccountContext.Provider value={{ ...value, customers }}>
{children}
</AccountContext.Provider>
)
};
Any can be anything not only array, so it will not have a map method. Use const customers:any[] = useContext() instead
I have a problem testing the component
import React from "react";
import { useSelector } from "react-redux";
import { PopupListWrapper, Song } from "./PopupListStyles";
const PopupList = () => {
const selectedAlbum = useSelector((state) => state.album);
return (
<PopupListWrapper data-testid="popupList-test">
{selectedAlbum.map((song) => {
const { trackName, trackTime } = song;
return (
<Song key={trackName}>
<p>{trackName}</p>
<p>{trackTime}</p>
</Song>
);
})}
</PopupListWrapper>
);
};
export default PopupList;
I want to check if it redner, but I still have a problem with its internal function
import { render } from "#testing-library/react";
import "#testing-library/jest-dom/extend-expect";
import configureStore from "redux-mock-store";
import { Provider } from "react-redux";
import * as reactRedux from "react-redux";
import PopupList from "./PopupList";
describe("<PopupAlbumInformation/>", () => {
const initialState = {
selectedAlbum: [],
};
const mockStore = configureStore();
let store;
const useSelectorMock = jest.spyOn(reactRedux, "useSelector");
beforeEach(() => {
useSelectorMock.mockClear();
});
it("whether the component PopupList is rendering", () => {
store = mockStore(initialState);
useSelectorMock.mockReturnValue({ initialState });
const { selectedAlbum } = initialState;
const { getByTestId } = render(
<Provider store={store}>
<PopupList>{selectedAlbum}</PopupList>
</Provider>
);
});
});
And here is error
TypeError: selectedAlbum.map is not a function
10 | return (
11 | <PopupListWrapper data-testid="popupList-test">
> 12 | {selectedAlbum.map((song) => {
| ^
13 | const { trackName, trackTime } = song;
14 | return (
15 | <Song key={trackName}>
yes i know i don't have an assertion yet but because of this problem i can't go any further.
Any help?
There is no need to mock nor spy on the selector. Just wrap the component in redux provider, pass correct initial state and you are absolutely gucci
Hi I am creating a react app using reduxtoolkit it has addto cart function I am trying to update the add to cart button using redux state, when I am getting redux actions for increment and decrement its showing an error ReferenceError: Cannot access 'selectadto' before initialization not sure what I am missing here, if anyone knows please do check
my component is below
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { selectAddSlice } from "./features/auth/addsSlice";
import { selectadto } from "./features/auth/addtoSlice";
import { increment, decriment } from "./features/auth/addtoSlice";
const Addtocart = (props) => {
const dispatch = useDispatch();
const selectedAdds = useSelector(selectAddSlice);
const selectedTodo = useSelector(selectadto);
useEffect(() => {
console.log(selectedTodo);
}, [selectedTodo]);
const onIncrementclicked = (e) => {
e.preventDefault();
dispatch(increment());
};
const onDecrimentclicked = (e) => {
e.preventDefault();
dispatch(decriment());
};
return (
<div>
{selectedAdds.map((add) => (
<div key={add.id}>
<div> {add.addname}</div>
<div> {add.price}</div>
<button onClick={onIncrementclicked()}>{selectedTodo}</button>
<button onClick={onDecrimentclicked()}>{selectedTodo}</button>
</div>
))}
</div>
);
};
export default Addtocart;
my redux slices is below
import { createSlice } from '#reduxjs/toolkit';
export const addtoSlice = createSlice({
name: 'addto',
initialState: {
currentamount: 0
},
reducers: {
increment: state => {
state.curentamount++
},
decriment: state => {
state.currentamount--
},
},
});
export const { increment, decriment } = addtoSlice.actions;
export const selectadto = state => state.addto.currentamount;
export default addtoSlice.reducer;
the error message is below
TypeError: Cannot read property 'preventDefault' of undefined
onIncrementclicked
src/Addtocart.js:17
14 | console.log(selectedTodo);
15 | }, [selectedTodo]);
16 | const onIncrementclicked = (e) => {
> 17 | e.preventDefault();
| ^ 18 | dispatch(increment());
19 | };
20 | const onDecrimentclicked = (e) => {
In const selectadto = useSelector(selectadto); you declare a new variable called selectadto while using a reducer named selectadto. You should probably give one of the two a different name.
I'm trying to use the useSnack hook from notistack library but I keep getting this error
TypeError: Cannot destructure property 'enqueueSnackbar' of 'Object(...)(...)' as it is undefined.
Here is the code:
import React, { useContext, useEffect } from "react";
import AlertContext from "../context/alert/alertContext";
import { SnackbarProvider, useSnackbar } from "notistack";
const Alerts = (props) => {
const alertContext = useContext(AlertContext);
// This line below is where the error seems to be
const { enqueueSnackbar } = useSnackbar();
useEffect(() => {
alertContext.msg !== "" &&
enqueueSnackbar(alertContext.msg, {
variant: alertContext.type,
});
}, [alertContext]);
return <SnackbarProvider maxSnack={4}>{props.children}</SnackbarProvider>;
};
export default Alerts;
useSnackbar hook accessible anywhere down the tree from SnackbarProvider.
So you cannot use it in the same component as SnackbarProvier.
import AlertContext from "../context/alert/alertContext";
import { SnackbarProvider } from "notistack";
const Alerts = (props) => {
const alertContext = useContext(AlertContext);
const providerRef = React.useRef();
useEffect(() => {
alertContext.msg !== "" &&
providerRef.current.enqueueSnackbar(alertContext.msg, {
variant: alertContext.type,
});
}, [alertContext]);
return <SnackbarProvider ref={providerRef} maxSnack={4}>
{props.children}
</SnackbarProvider>;
};
export default Alerts;
Wrap you index file with SnapBar provider:
index.js
import { SnackbarProvider } from "notistack";
const Index = () => (
<SnackbarProvider maxSnack={1} preventDuplicate>
index
</SnackbarProvider>
)
export default Index
jsx file
import { useSnackbar } from "notistack";
const Logs = () => {
const { enqueueSnackbar } = useSnackbar();
const handler = () => {
enqueueSnackbar(`Successful.`, { variant: "success" });
};
return <span onClick={handler}>"Logs loading"</span>;
};
export default Logs;