So, in my code, i am loading the Select options and the options i am loading are based on the calculation of possibleSubnets for a netMask, for example /64 will have so many records in dropdown.
With my current implementation, it lags when it has to do so much of calculation in Options. Thus page becomes unresponsive.
import React, { useEffect, useState, useRef } from 'react';
import { Row, Col, Button, Form, Input, Space, Alert, Drawer, Divider } from 'antd';
import { useQuery, useMutation } from "@apollo/client";
import { TextInput, Select } from '../../components/pants-d';
import { NetmaskForm } from '../../components/SubnetBuilder';
import { possibleSubnets } from '../../components/SubnetBuilder/V4';
import cidrRegex from 'cidr-regex';
import { possibleSubnets as v6PossibleSubnets } from '../../components/SubnetBuilder/V6';
import debounce from 'lodash/debounce';
const { Option } = Select;
const subnet = require("../../entities/subnet");
const zone = require('../../entities/zone')
const SubnettingForm = ({ supernetId, networkAddress, onCreate, onClose }) => {
const [errors, setErrors] = useState([])
const [open, setOpen] = useState(true);
const [childSubnets, setChildSubnets] = useState([]);
const [showSelect, setShowSelect] = useState(false);
const [createRecord, { data: createData, loading: createLoading, error: createErrors }] = useMutation(subnet.create, {
onCompleted: ({ createSubnet: subnet }) => {
onClose()
},
onError: (err) => {
const message = err?.message
setErrors([{ message: (message.charAt(0).toUpperCase() + message.slice(1)).replaceAll('\"', '') }])
}
});
const { loading, error, data, refetch } = useQuery(subnet.GET_QUERY, { variables: { id: parseInt(supernetId) } });
const [netmask, setNetmask] = useState();
const [optionsLoading, setOptionsLoading] = useState(false); // Loading state for options
const [subnetOptions, setSubnetOptions] = useState([]); // Options for the Select
const supernet = data?.subnet?.networkAddress
const [form] = Form.useForm();
const isV4 = cidrRegex.v4({ exact: true }).test(data?.subnet?.networkAddress)
useEffect(() => {
let calculatedChildSubnets
if (netmask) {
if (isV4) {
calculatedChildSubnets = possibleSubnets(data.subnet, netmask);
} else {
calculatedChildSubnets = v6PossibleSubnets(data.subnet, netmask)
}
setChildSubnets(calculatedChildSubnets);
setShowSelect(true);
} else {
setShowSelect(false);
}
}, [netmask, supernet]);
return (
<Drawer
title={`Create a subnet in ${data?.subnet?.networkAddress}`}
onClose={onClose}
width={520}
visible={open}>
<Form
layout="vertical"
form={form}
name="subnet"
onFinish={({ networkAddress, netmask, zone, ...values }) => {
createRecord({ variables: { ...values, networkAddress: `${networkAddress}`, supernetId: supernetId } })
}} >
{errors && errors.map(error => {
return (<><Alert type="error" message={error.message} /><br /></>)
})}
<Form.Item label="Netmask">
<NetmaskForm limit={10} netmask={parseInt(data?.subnet?.networkAddress.split('/')[1])} onSelect={(v) => { setNetmask(v) }} defaultValue=' ' />
</Form.Item>
<Form.Item label="Subnet">
<Select>
{childSubnets.map((subnet) => (
<Option key={subnet.id} value={subnet.id}>
{subnet.networkAddress}
</Option>
))}
</Select>
</Form.Item>
<TextInput name="name" />
<Row style={{ marginTop: '40px' }}>
<Col span={24}>
<Button type="secondary" onClick={e => { onClose() }} style={{ float: 'right', marginLeft: '20px' }}>
Cancel
</Button>
<Button type="primary" htmlType="submit" style={{ float: 'right', marginLeft: '20px' }}>
Submit
</Button>
</Col>
</Row>
</Form>
</Drawer>
)
}
export default SubnettingForm;
I am thinking, if we can lazy load or debounce the data on scroll in options, like load 10 options first and then load more when reached in the end of scroll.