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
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>
);
};
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
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
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;
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.