Converting React TypeScript to React js - reactjs

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;

Related

TypeError: Cannot read properties of null (reading 'useContext')

I want add {searchWord} from useContext, to function with API call getServerSideProps(), but I got different errors.
The last one: Cannot read properties of null (reading 'useContext').
Maybe something wrong with my provider???
File with API call function /search-results:
import Link from 'next/link';
import { Text, Stack, Box, SimpleGrid, IconButton, Button, useQuery } from '#chakra-ui/react'
import ListOfCards from '../components/ListOfCards';
import { SearchContext, SearchContextProps } from './_app';
import { useContext, useEffect, useState } from 'react';
import { ChevronLeftIcon } from '#chakra-ui/icons';
function SearchResult({ searchResultForMapping }) {
console.log(searchResultForMapping)
const [queryKey, setQueryKey] = useState('lebowski');
const { searchWord } = useContext<SearchContextProps>(SearchContext);
useEffect(() => {
setQueryKey(searchWord);
}, [searchWord]);
const mockup = {"status":"OK","copyright":"Copyright (c) 2022 The New York Times Company. All Rights Reserved.","has_more":false,"num_results":1,"results":[{"display_title":"The Big Lebowski","mpaa_rating":"R","critics_pick":1,"byline":"Janet Maslin","headline":"Big Lebowski, the (Movie)","summary_short":"In a film both sweeter and loopier than \u0026quot;Fargo,\u0026quot; Joel and Ethan Coen and their rogues' gallery of actors explore Southern California's post-hippie, surfer-dude bowling scene. The results are irresistible, at least for audiences on the film's laid-back wavelength and in tune with its deadpan humor. With shaggy, baggy looks that belie his performance's fine comic control, Jeff Bridges plays a guy who truly deserves to be called Dude, and is by turns oblivious and indignant once a ruined rug leads him into neo-noir escapades. In a film that certainly keeps its audience guessing what might happen next (Saddam Hussein renting bowling shoes?), John Turturro takes the cake as the most fiendish of bowlers. — Janet Maslin","publication_date":"1998-03-06","opening_date":"1998-03-06","date_updated":"2017-11-02 04:17:54","link":{"type":"article","url":"https://www.nytimes.com/1998/03/06/movies/film-review-a-bowling-ball-s-eye-view-of-reality.html","suggested_link_text":"Read the New York Times Review of The Big Lebowski"},"multimedia":null}]}
return (
<><Button leftIcon={<ChevronLeftIcon />} colorScheme='pink' variant='solid' position='absolute' right='20px;' top='25px'>
<Link href="/">Home</Link>
</Button>
<Box p={5}>
<SimpleGrid gap={12} p={12} columns={1}>
<Text fontSize='4xl'> Search Result for keyword "{queryKey} i {searchWord}"</Text>
<Stack spacing={3} rowGap={3}>
<ListOfCards movieDetails={mockup} />
</Stack>
<Text fontSize='xl'><Link href="/">Search last key word..</Link> </Text>
</SimpleGrid>
</Box></>
);
}
const { searchWord } = useContext<SearchContextProps>(SearchContext);
export async function getServerSideProps() {
// const queryWord = 'iron'
const queryWord = searchWord;
const apiKey = "nTCRt5WnuaiL5Q5VsPEgeGM8oZifd3Ma";
const endpoint = "https://api.nytimes.com/svc/movies/v2/reviews/search.json?";
const createUrl = `${endpoint}query=${queryWord}&api-key=${apiKey}`;
const res = fetch(createUrl);
const searchResultForMapping = (await res).json();
return { props: { searchResultForMapping } };}
export default SearchResult
Page where i setSearchWord SearchLine.tsx:
import { Button } from "#chakra-ui/button";
import { Input, InputGroup, InputRightElement } from "#chakra-ui/input";
import React, { useContext } from "react";
import { useRouter } from 'next/router'
import { SearchContext } from "../pages/_app";
const SearchLine = () : JSX.Element => {
const { searchWord, setSearchWord, searchHistory, setSearchHistory } = useContext(SearchContext);
const router = useRouter()
const handleChange = (keyword) => setSearchWord(keyword.target.value);
const handleOnclick = () => {
setSearchHistory([...searchHistory, searchWord]);
router.push('/search-result');
}
return (
<InputGroup size="md">
<Input
onChange={handleChange}
placeholder='Enter the name of the movie or keyword'
size='md'
/>
<InputRightElement width="4.5rem">
<Button onClick={handleOnclick}>
Enter
</Button>
</InputRightElement>
</InputGroup>
)
}
export default SearchLine;
my _app.tsx:
import { ChakraProvider } from '#chakra-ui/react'
import { QueryClientProvider } from '#tanstack/react-query';
import { AppProps } from 'next/app';
import { createContext, useContext, useMemo, useState } from 'react';
export interface SearchContextProps {
searchWord: string;
setSearchWord: (f: string) => void;
searchHistory: string[];
setSearchHistory: (f: string[]) => void;
}
export const SearchContext = createContext<SearchContextProps>({
searchWord: '',
setSearchWord: () => {
// do nothing
},
searchHistory: [],
setSearchHistory: () => {
// do nothing
},
});
const SearchProvider = (props: any) => {
const [searchWord, setSearchWord] = useState('');
const [searchHistory, setSearchHistory] = useState('');
const value = useMemo(() => ({ searchWord, setSearchWord, searchHistory, setSearchHistory }), [searchWord]);
return <SearchContext.Provider value={value} {...props} />;
};
function MyApp({ Component, pageProps }: AppProps): JSX.Element {
const context = useContext(SearchContext);
return (
<ChakraProvider>
<SearchProvider>
<Component {...pageProps} />
</SearchProvider>
</ChakraProvider>
)
}
export default MyApp
It seems your SearchProvider is wrong.
const SearchProvider = (props: any) => {
const [searchWord, setSearchWord] = useState('');
const [searchHistory, setSearchHistory] = useState('');
const value = useMemo(() => ({ searchWord, setSearchWord, searchHistory, setSearchHistory }), [searchWord]);
return (
<SearchContext.Provider value={value}>
{props.children}
</SearchContext.Provider>
);
};

Using TanStack Query with Child

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

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

reactjs: Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>

The error happens in this part:
const {playing, bannerOpen} = useSelector(state => state.musicReducer);
I have searched for information, but I cannot fix it.
Apparently I only get that error in that part, I am a newbie and there are things that I do
not understand yet.
import React, { useContext, useEffect, useState } from "react";
import { ThemeContext } from "../components/Theme";
import AddMusic from "../fragment/AddMusic";
import BottomNavigationMobile from "../fragment/BottomNavigationMobile";
import CurrentPlayingLarge from "../fragment/CurrentPlayingLarge";
import FooterMusicPlayer from "../fragment/FooterMusic";
import FooterSelectMusic from "../fragment/FooterSelectMusic";
import MobileTopNavigation from "../fragment/MobileTopNavigation";
import MusicCardContainer from "../fragment/MusicCardContainer";
import Navigation from "../fragment/Navigation";
import Playlist from "../fragment/Playlist";
import SideBar from "../fragment/SideBar";
import About from "./About";
import './css/Home.scss';
import Profile from "./Profile";
import Search from "./Search";
import {useSelector} from 'react-redux';
function getCurrPage(pathName) {
switch (pathName) {
case "/home":
return <MusicCardContainer/>
case "/home/search":
return <Search/>
case "/home/profile":
return <Profile/>
case "/home/add":
return <AddMusic/>
case "/home/about":
return <About/>
default:
if (pathName.startsWith("/home/playlist/")){
return <Playlist/>
}
return null
}
}
function Home() {
const [screenSize, setScreenSize] = useState(undefined);
const [currMusic, setCurrMusic] = useState(null);
const [Page, setCurrPage] = useState(<MusicCardContainer/>);
let pathname = window.location.pathname;
useEffect(() => {
setCurrPage(getCurrPage(pathname))
}, [pathname]);
window.addEventListener("resize", handleResize);
function handleResize() {
setScreenSize(window.innerWidth);
}
useEffect(() => {
handleResize();
return () => window.removeEventListener("resize", handleResize);
});
const useStyle = useContext(ThemeContext);
const {playing, bannerOpen} = useSelector(state => state.musicReducer);
useEffect(() => {
setCurrMusic(playing)
}, [playing])
return (
<div style={useStyle.component} className={"home-container"}>
{
screenSize <= 970 ?
<MobileTopNavigation/> :
<Navigation/>
}
<section className={"home-music-container"}>
<div className="sidebar-home">
<SideBar/>
</div>
<div className="main-home">
{
Page
}
</div>
</section>
{
bannerOpen
&&
<section className="current-large-banner">
<CurrentPlayingLarge/>
</section>
}
<React.Fragment>
{
currMusic
?
<FooterMusicPlayer music={currMusic}/>
:
<FooterSelectMusic/>
}
{
screenSize <= 970 && <BottomNavigationMobile/>
}
</React.Fragment>
</div>
);
}
export default Home;

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