I am trying to do an onClick event in a react Modal. When I fire the onClick event I would like for it to issue a component form. The onClick event seems to work, but when it renders the component it is throwing the following error.
TypeError: Cannot read properties of undefined (reading 'toString')
Which seems to be coming from the following line in the Component Form
const page = parseInt(router.query.page.toString());
I have placed the code below for inspection
Modal:
import React, {useState} from 'react';
import { observer } from 'mobx-react-lite'
import { useDataStore } from 'stores/data';
import Space from './Space';
import { Plus } from 'components/Icons'
import ShowNetworkInfo from '../../components/Forms/ShowNetworkInfo';
import SpaceDirectory, { Header, Title, Options, Option, OptionIcon, OptionLabel } from "styles/SpaceDirectory/SpaceDirectory";
const SPACE_DIRECTORY = observer((props) => {
const [isInfoShown, setInfoShown] = useState(false);
const handleClick = (event) => {
event.preventDefault();
setInfoShown(true);
}
const { spaceStore } = useDataStore();
const spaces = spaceStore.spaces?.map(space => (
<Space
key={space.id}
space={space}
/>
))
return (
<SpaceDirectory>
<Header>
<Title>SPACES</Title>
<Options>
<Option onClick={async () => console.log("ADD SPACE") }>
<OptionIcon>
<Plus />
</OptionIcon>
<OptionLabel>
SPACE
</OptionLabel>
</Option>
</Options>
<Options>
<Option type='submit' onClick={handleClick} >
{isInfoShown && <ShowNetworkInfo/>}
<OptionIcon>
<Plus />
</OptionIcon>
<OptionLabel>
ADD NETWORK
</OptionLabel>
</Option>
</Options>
</Header>
{ spaces }
</SpaceDirectory>
);
});
export default SPACE_DIRECTORY
The onClick event fires and takes me to the following component:
Component:
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router';
import { useEffect, useMemo, useState } from 'react';
import NetworkInformation from 'components/Forms/NetworkInformation';
import ShowNetworkInfo, { Header, FormNav, FormNavItem, FormBody } from 'styles/Forms/ShowNetworkInfo'
import { useDataStore } from 'stores/data';
import { Product } from 'models/Product';
type NetworkNode = any;
type Order = {
selectedNetwork:Product
items:Array<NetworkNode>
}
const SHOW_NETWORK_INFO = observer(() => {
const router = useRouter();
const page = parseInt(router.query.page?.toString())
const { productStore } = useDataStore()
const [order, setOrder] = useState<Order>({
selectedNetwork:null,
items:[]
});
useEffect(() => {
const page = parseInt(router.query.page.toString());
if ( order.selectedNetwork && page === 1 )
router.push({ pathname:router.pathname, query: { ...router.query, page:2 }})
if ( !order.selectedNetwork && page > 1 )
router.push({ pathname:router.pathname, query: { ...router.query, page:1 }})
},[ order.selectedNetwork ])
const FormOptions = useMemo(() => {
const options = [];
switch(page){
case 1:
options.push(
<NetworkInformation
key={`network-catalog`}
selectedNetwork={order.selectedNetwork}
selectNetwork={( productId ) => {
const targetProduct = productStore.products.find(product => product.pid === productId )
productId === order.selectedNetwork?.pid ?
router.push({ pathname:router.pathname, query: { ...router.query, page:2 }}) :
setOrder({ ...order, selectedNetwork:targetProduct })
}}
/>
)
break;
}
return options;
}, [page]);
return (
<ShowNetworkInfo>
<Header>Network Information</Header>
{/* <FormNav>
<FormNavItem
data-active={page === 1}
onClick={() => {
if( page !== 1 )
router.push({
pathname:router.pathname,
query: { ...router.query, page:1 }
})
}}>
1. SELECT
</FormNavItem>
<FormNavItem
data-active={page === 2}
onClick={() => {
if( page !== 2 && !!order.selectedNetwork )
router.push({
pathname:router.pathname,
query: { ...router.query, page:2 }
})
}}>
2. CONFIGURE
</FormNavItem>
<FormNavItem
data-active={page === 3}
onClick={() => {
if( page !== 3 )
router.push({
pathname:router.pathname,
query: { ...router.query, page:3 }
})
}}>
3. DEPLOY
</FormNavItem>
</FormNav> */}
<FormBody>
{ FormOptions }
</FormBody>
</ShowNetworkInfo>
)
});
export default SHOW_NETWORK_INFO
CodePudding user response:
router.query = {} in first render of the nextjs,
you have to add router.query.page to the dependencies array of the useEffect
useEffect(() => {
if(!router.query.page) return;
const page = parseInt(router.query.page.toString());
if ( order.selectedNetwork && page === 1 )
router.push({ pathname:router.pathname, query: { ...router.query, page:2 }})
if ( !order.selectedNetwork && page > 1 )
router.push({ pathname:router.pathname, query: { ...router.query, page:1 }})
},[ order.selectedNetwork, router.query.page ])