Using TanStack Query with Child - reactjs

i want to use query inside child object of Category but im gettin this error.
Unhandled Runtime Error Error:
QueryClientProvider to set one No QueryClient set, use QueryClientProvider to set one
pages/category/[pid].js
15 | heading: pid,
16 | };
> 17 | const { data, isLoading } = useQuery(["movieImage"], get);
| ^
18 | if (isLoading) {
19 | return <div>Loading...</div>;
20 | }
index.js
import Banner from '../components/Banner';
import Category from '../components/Category';
import LiveAuction from '../components/LiveAuction';
import TopCollectors from '../components/TopCollectors';
import TrendingNow from '../components/TrendingNow';
import { ReactQueryDevtools } from "react-query/devtools";
import {
QueryClient,
QueryClientProvider,
} from "react-query";
import { Fragment } from 'react';
const queryClient = new QueryClient();
const Home = () => {
return (
<Fragment>
{" "}
<QueryClientProvider client={queryClient} contextSharing={true}>
<Banner />
<Category />
<LiveAuction />
<TopCollectors />
<TrendingNow />
<ReactQueryDevtools initialIsOpen={true} />
</QueryClientProvider>
</Fragment>
);
}
export default Home
some part of pages/category/[pid].js
const { pid } = router.query;
const { data, isLoading } = useQuery(["movieImage"], getGenres);
if (isLoading) {
return <div>Loading...</div>;
}
tried to change ReactQueryDevtools position
added Fragment
added contextSharing={true} to QueryClientProvider

Related

react test component based on conditional component in parent component with react testing library

I'm trying to test component that is wrapped with other component, the parent component has conditional rendering, for explanation:
import React, { FunctionComponent } from 'react'
import { getPermissions, ROLES, PERMISSIONS } from '~/constants/permissions'
import usePermission from '~/hooks/usePermission'
export interface UsePermissionParams {
as: ROLES;
children?: React.ReactNode;
permissions: PERMISSIONS[];
}
// This Component is used to check if the user has the permission to access Specific Component or part of the UI
const CanAccess: FunctionComponent<UsePermissionParams> = ({
as,
children,
permissions,
}) => {
const hasPermission = usePermission({ permissions })
if (as === ROLES.VENDOR) {
const hasAllPermissions = permissions?.every((permission) =>
getPermissions.vendor.includes(permission)
)
if (hasPermission && hasAllPermissions) {
return <>{children}</>
}
} else if (as === ROLES.ADMIN) {
const hasAllPermissions = permissions?.every((permission) =>
getPermissions.admin.includes(permission)
)
if (hasPermission && hasAllPermissions) {
return <>{children}</>
}
}
return <></>
}
export default CanAccess
this is the parent component that wrap the component that I need to test.
and this is the component that I want to test:
import React, { useContext, useState } from 'react'
import { CircularProgress } from '#mui/material'
import { useSelector } from 'react-redux'
import CanAccess from '~/components/CanAccess'
import CreateBox from '~/components/CreateBox'
import { ROLES, PERMISSIONS } from '~/constants/permissions'
import CardHolder from '~/modules/finance/Components/SponsoredProductsTab/Components/CardHolder'
import TopUpModal from '~/modules/finance/Components/TopUpModal'
import { FinanceContext } from '~/modules/finance/FinanceContext'
import * as styles from '~/modules/finance/styles'
import { State } from '~/store'
import { User } from '~/store/user/types'
import { i18n } from '~/translations/i18n'
import { currencySign } from '~/utils/getCurrencySign'
import { ls } from '~/utils/localStorage'
import { separator } from '~/utils/numberSeperator'
const AccountBalance = () => {
const { list, loading } = useContext<any>(FinanceContext)
const [showTopUpModal, setShowTopUpModal] = useState<boolean>(false)
const userRepresentation = useSelector<State, User | null>(
(state) => state.user.data
)
const targetSelected = ls.get('target_code')
const handleOpenTopUpModal = () => {
setShowTopUpModal(true)
}
const onClose = () => {
setShowTopUpModal(false)
}
const renderCreateTopUP = () => (
<CanAccess as={ROLES.VENDOR} permissions={[PERMISSIONS.FO_TOPUP_ACCESS]}>
<CreateBox
label="Top Up"
maxWidth="fit-content"
handleCreateCampaign={handleOpenTopUpModal}
/>
</CanAccess>
)
return (
<>
{showTopUpModal && (
<TopUpModal
onClose={onClose}
advertiserId={
userRepresentation == null
? 0
: userRepresentation?.advertiserId || 0
}
target={targetSelected}
open
/>
)}
<CardHolder
cardHeader="Your account balance:"
cardContent={`${currencySign() || ''} ${
separator(list?.balance) || '0'
}`}
CardBottom={renderCreateTopUP()}
/>
</>
)
}
export default AccountBalance
and this is the test file:
import AccountBalance from '.'
import { render, screen } from '~/test-utils'
describe('AccountBalance', () => {
it('should render the top up button', async () => {
render(<AccountBalance />)
const topUpBtn = await screen.findByText('Top up')
expect(topUpBtn).toBeInTheDocument()
})
})
and I have this error:
<body>
<div>
<div
class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-s9smhs-MuiPaper-root"
>
<div>
<p
class="MuiTypography-root MuiTypography-body1 css-1tvvmmg-MuiTypography-root"
>
Your account balance:
</p>
<p
class="MuiTypography-root MuiTypography-body1 css-1hd1hip-MuiTypography-root"
>
0
</p>
<div
class="css-0"
/>
</div>
</div>
</div>
</body>
5 | it('should render the top up button', async () => {
6 | render(<AccountBalance />)
> 7 | const topUpBtn = await screen.findByText('Top up')
| ^
8 | expect(topUpBtn).toBeInTheDocument()
9 | })
10 | })
the problem is: any component that is wrapped with the component CanAccess is not rendering and I have null
so what is the problem

Unit test for component in react

hi i am new to react testing and i am using react testing library and jest.please help me in writing test case for below code.
import React from 'react'
import {
Loader,
SectionTitle,
ErrorLabel,
} from 'LookingGlass/common/components'
import LookingGlassPanelResultSection from 'LookingGlass/app/components/LookingGlassResultSection'
import constants from 'LookingGlass/constants'
import getErrorMessage from 'LookingGlass/app/utils/getErrorMessage'
import styles from './_.index.module.scss'
export default function LookingGlassPanelResults(props) {
const { queryResult, isTimedOut, error, isServerDown, isLoading } = props
if (isLoading)
return (
<Loader
content={constants.Loader.loaderContent}
active
inline="centered"
size="large"
/>
)
if (isServerDown) {
return <ErrorLabel text={constants.error.message.error_404} />
}
if (isTimedOut) {
return <ErrorLabel text={constants.requestsTimeout.msg} />
}
if (error) {
return <ErrorLabel text={getErrorMessage(error)} />
}
if (!queryResult) return null
return (
<div>
<hr className={styles.seperateLine} />
<SectionTitle text={constants.QueryPanelResult.resultPanel} />
<LookingGlassPanelResultSection queryResult={queryResult} />
</div>
)
}
ErrorLabel is different component where icon is used and text is displayed. How to write test where we use component inside component ?
this is my test case:-
const renderComponent = (props) =>
render(<LookingGlassPanelResults {...props} />)
test('Verify that isServerDown parameter works', () => {
const component = renderComponent({ isServerDown: true })
const { getByText } = within(component)
expect(
getByText('Service unavailable. Please try later'),
).toBeInTheDocument()
})
Error:-`
TypeError: Expected container to be an Element, a Document or a DocumentFragment but got Object.
20 | const { getByText } = within(component)
21 | expect(
> 22 | getByText('Service unavailable. Please try later'),
| ^
23 | ).toBeInTheDocument()
24 | })`
here first we need to get ErrorLabel by test-id and then check expectations
test('Verify that isServerDown parameter works', () => {
const component = renderComponent({ isServerDown: true })
const { getByTestId } = component
expect(getByTestId('ErrorLabel')).toHaveTextContent(
'Service unavailable. Please try later',
)
})

Converting React TypeScript to React js

I am new to coding and I was wondering if someone can show me how to convert this code that was shared on Sandbox from 'React TypeScript ' to 'React js'.
import * as React from "react";
import { render } from "react-dom";
import {TreeView, TreeItem, TreeItemProps, TreeViewProps} from "#material-ui/lab"
import ExpandMoreIcon from "#material-ui/icons/ExpandMore";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
function TreeItemX(props:TreeItemProps &{iconClickOnly:boolean}){
// todo should call the original
const handler:TreeItemProps['onLabelClick'] = evt => evt.preventDefault();
const {iconClickOnly,...others} = props;
const handledProps:TreeItemProps ={
...others,
[props.iconClickOnly?'onLabelClick':'onIconClick']:handler
}
return <TreeItem {...handledProps} />
}
function TreeViewX(props:TreeViewProps&{defaultPreventedPrevents:boolean}){
const {defaultPreventedPrevents,...others} = props;
const originalOnNodeSelect = props.onNodeSelect;
const preventingOnNodeSelect = (evt:React.ChangeEvent<{}>, nodeId:string&string[]) => {
if(defaultPreventedPrevents){
if(!evt.defaultPrevented){
originalOnNodeSelect?.(evt,nodeId)
}
}else{
if(evt.defaultPrevented){
originalOnNodeSelect?.(evt,nodeId)
}
}
}
return <TreeView {...others} onNodeSelect={preventingOnNodeSelect}/>
}
function App(){
const [selected,setSelected] = React.useState<string>('')
return (
<TreeViewX
defaultPreventedPrevents={true}
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
selected={selected}
onNodeSelect={(_,id)=>{
setSelected(id);
}}>
<TreeItemX iconClickOnly nodeId='parent' label='Parent'>
<TreeItemX iconClickOnly nodeId='child' label='Child'/>
</TreeItemX>
</TreeViewX>
);
}
render(<App />, document.getElementById("root"));
Thank you in advance.
A good start would be to remove the types, for example:
function TreeItemX(props){
const handler = evt => evt.preventDefault();
const { iconClickOnly, ...others } = props;
const handledProps ={
...others,
[props.iconClickOnly ? 'onLabelClick' : 'onIconClick']
}
return <TreeItem {...handledProps} />
}
Just continue doing this, until you have your React code without the types in it.
Thank you so much for your assistance. I get the following error when I attempt to compile:
./src/App.js Line 17:3: Parsing error: Unexpected token
15 | ...others, 16 | [props.iconClickOnly ? 'onLabelClick'
: 'onIconClick']
17 | }
| ^ 18 | return 19 | } 20 |
Below is the code so far:
import React from "react";
import TreeView from "#material-ui/lab/TreeView";
import ExpandMoreIcon from "#material-ui/icons/ExpandMore";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
import TreeItem from "#material-ui/lab/TreeItem";
import "./App.css";
function TreeItemX(props){
const handler = evt => evt.preventDefault();
const { iconClickOnly, ...others } = props;
const handledProps ={
...others,
[props.iconClickOnly ? 'onLabelClick' : 'onIconClick']
}
return <TreeItem {...handledProps} />
}
function TreeViewX(props){
const {defaultPreventedPrevents,...others} = props;
const originalOnNodeSelect = props.onNodeSelect;
const preventingOnNodeSelect = (evt, nodeId) => {
if(defaultPreventedPrevents){
if(!evt.defaultPrevented){
originalOnNodeSelect?.(evt,nodeId)
}
}else{
if(evt.defaultPrevented){
originalOnNodeSelect?.(evt,nodeId)
}
}
}
return <TreeView {...others} onNodeSelect={preventingOnNodeSelect}/>
}
function App() {
return (
<div className="App">
<TreeViewX
defaultPreventedPrevents={true}
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
selected={selected}
onNodeSelect={(_,id)=>{
setSelected(id);
}}>
<TreeItemX iconClickOnly nodeId='parent' label='Parent'>
<TreeItemX iconClickOnly nodeId='child' label='Child'/>
</TreeItemX>
</TreeViewX>
);
</div>
);
}
export default App;

Struggling to get some data from api

Hi i'm trying to get some data from "currency API" (https://exchangeratesapi.io/)
and this is code below
App.js
import React, { useEffect, useState, Fragment } from "react";
import Header from "./Header";
import Table from "./dashboard/Table";
import { getLatest } from "../actions/currencyAction";
import { useDispatch, useSelector } from "react-redux";
function App() {
const latest = useSelector(state => state.latest);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getLatest());
}, []);
return (
<Fragment>
<Header />
{console.log(latest.rates)}
</Fragment>
);
}
export default App;
currencyAction.js
import { GET_LATEST } from "../actionType";
import axios from "axios";
export function getLatest() {
return dispatch => {
return axios.get("https://api.exchangeratesapi.io/latest").then(res => {
dispatch({ type: GET_LATEST, payload: res.data });
});
};
}
I succesfully got the data from api
<Fragment>
<Header />
{console.log(latest.rates)}
</Fragment>
{CAD: 1.4372, HKD: 8.4324, ISK: 139.3, PHP: 55.248, DKK: 7.4699, …}
CAD: 1.4372
HKD: 8.4324
ISK: 139.3
PHP: 55.248
DKK: 7.4699
HUF: 337.61
CZK: 25.186
AUD: 1.6384
RON: 4.8063
SEK: 10.5833
IDR: 15098.95
INR: 77.8265
BRL: 4.7474
RUB: 70.6675
HRK: 7.465
JPY: 120.52
THB: 34.336
CHF: 1.06
SGD: 1.5164
PLN: 4.2989
BGN: 1.9558
TRY: 6.6599
CNY: 7.6102
NOK: 10.1328
NZD: 1.7095
ZAR: 16.3592
but when I'm trying acces each currency, Everthing collapse..
<Fragment>
<Header />
{console.log(latest.rates.CAD)}
</Fragment>
TypeError: Cannot read property 'CAD' of undefined
App
C:/Users/82102/cb/src/components/App.js:17
14 |
15 | return (
16 | <Fragment>
> 17 | <Header />
| ^ 18 | {console.log(latest.rates.CAD)}
19 | </Fragment>
20 | );
I struggled for whole day long but I just can't figure out why it's happening..
please share your knowledge.. thank you
You're trying to access a property on rates before it has been loaded from the API.
The easy solution is to check its existence first:
Make sure rates is truthy (since typeof null === 'object' is also true),
Check type to see if its an object,
Then access the property.
{latest.rates && typeof latest.rates === 'object' && console.log(latest.rates.CAD)}
Because you use console.log in return causes an error.
You should do the following:
import React, { useEffect, useState, Fragment } from "react";
import Header from "./Header";
import Table from "./dashboard/Table";
import { getLatest } from "../actions/currencyAction";
import { useDispatch, useSelector } from "react-redux";
function App() {
const latest = useSelector(state => state.latest);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getLatest());
}, []);
// add here
console.log(latest.rates)
return (
<Fragment>
<Header />
// remove below line
// {console.log(latest.rates)}
</Fragment>
);
}
export default App;

Jest / Enzyme not recognizing props

I am trying to write a test for a React functional component that uses Redux and Hooks.
I am using Jest with Enzyme for testing.
For Reference:
This is the functional component being tested:
import React from 'react';
import {useDispatch, useSelector} from "react-redux";
import * as actions from '../../actions/actions';
import { Button, Icon } from "#material-ui/core";
export const EditBatchHeaderComponent = (props) => {
const dispatch = useDispatch();
const { selectedBatch } = props;
const { batchName } = selectedBatch;
return (
<div className="edit-header-container">
<Button disableRipple onClick={() => {dispatch(actions.unSelectBatch())} }>
<Icon>arrow_back</Icon>
</Button>
<span>Edit Batch</span>
<span>{batchName}</span>
</div>
);
};
This is component's container:
import React from 'react';
import { BatchHeaderComponent } from './BatchHeaderComponent';
import { BatchTableComponent } from './BatchTableComponent';
import { EditBatchComponent } from './EditBatchComponent';
import {useSelector} from "react-redux";
import {EditBatchHeaderComponent} from "./EditBatchHeaderComponent";
export const BatchManagementComponent = () => {
const { selectedBatch } = useSelector(state => state.batchManagementReducer);
if (selectedBatch.length) {
return (
<div className="component-container">
<EditBatchHeaderComponent selectedBatch={selectedBatch} />
<EditBatchComponent selectedBatch={selectedBatch} />
</div>
);
}
return (
<div className="component-container">
<BatchHeaderComponent />
<BatchTableComponent />
</div>
);
};
This is the default state of the reducer:
{
sorting: {
order: '',
orderBy: ''
},
searchBy: 'batchName',
searchText: '',
filterByStatus: '--',
filterByType: '--',
waiting: false,
batchData: [],
selectedBatch: {
batchName: '',
},
}
This is the test file that is failing to recognize the props:
import React from 'react';
import { EditBatchHeaderComponent } from '../../../components/batchManagement/EditBatchHeaderComponent';
import configureStore from '../../../store';
import {Provider} from "react-redux";
import Enzyme, { mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import {Button} from "#material-ui/core";
Enzyme.configure({ adapter: new Adapter() });
describe('EditBatchHeaderComponent', () => {
it('mounts to the DOM successfully', () => {
const wrapper = mount(<Provider store={configureStore()}>
<EditBatchHeaderComponent />
</Provider>);
expect(wrapper.find(EditBatchHeaderComponent)).toBeDefined();
});
it('deselects the account and closes when the back button is clicked', () => {
const props = {selectedBatch: {batchName: 'INFORM'}, dispatch: jest.fn()};
const obj = {};
const wrapper = mount(
<Provider store={configureStore()}>
<EditBatchHeaderComponent {...props} />
</Provider>
);
console.log(wrapper.find(EditBatchHeaderComponent).props());
wrapper.find(Button).first().simulate('click');
expect(wrapper.find(EditBatchHeaderComponent)).toEqual(obj);
});
});
This is the error text provided by the test suite:
FAIL src/spec/components/batchManagement/EditBatchHeaderComponent.test.js (7.182s)
● EditBatchHeaderComponent › mounts to the DOM successfully
TypeError: Cannot read property 'batchName' of undefined
8 | const dispatch = useDispatch();
9 | const { selectedBatch } = props;
> 10 | const { batchName } = selectedBatch;
| ^
11 | return (
12 | <div className="edit-header-container">
13 | <Button disableRipple onClick={() => {dispatch(actions.unSelectBatch())} }>
I have run a nearly identical test on a similar component that runs and covers the code appropriately.
I can't seem to figure out why the props aren't being recognized.
Any assistance would be greatly appreciated, thanks.

Resources