Advanced Patterns
Advanced usage patterns and performance optimizations
Virtual Scrolling
Handle large lists efficiently with react-window.
import { FixedSizeList } from 'react-window';
import { allCountries } from 'countries-cities-ar';
function VirtualCountryList() {
const Row = ({ index, style }) => (
<div style={style} className="flex items-center p-2 border-b">
<span className="font-medium">{allCountries[index].nameAr}</span>
<span className="ml-2 text-gray-500">({allCountries[index].code})</span>
</div>
);
return (
<FixedSizeList
height={600}
itemCount={allCountries.length}
itemSize={50}
width="100%"
>
{Row}
</FixedSizeList>
);
}Dynamic Imports
Load data on demand to reduce initial bundle size.
// Lazy load regions
const loadAfricaCountries = async () => {
const { africaCountries } = await import('countries-cities-ar');
return africaCountries;
};
// In component
function RegionSelector() {
const [region, setRegion] = useState(null);
const [countries, setCountries] = useState([]);
const [loading, setLoading] = useState(false);
const loadRegion = async (regionName) => {
setLoading(true);
let data = [];
switch(regionName) {
case 'africa':
const { africaCountries } = await import('countries-cities-ar');
data = africaCountries;
break;
case 'asia':
const { asiaCountries } = await import('countries-cities-ar');
data = asiaCountries;
break;
// ... other regions
}
setCountries(data);
setLoading(false);
};
return (
<div>
<select onChange={(e) => loadRegion(e.target.value)}>
<option value="">Select Region</option>
<option value="africa">Africa</option>
<option value="asia">Asia</option>
<option value="europe">Europe</option>
</select>
{loading ? (
<div>Loading...</div>
) : (
<div className="grid grid-cols-3 gap-2 mt-4">
{countries.map(c => (
<div key={c.code}>{c.name}</div>
))}
</div>
)}
</div>
);
}Performance Optimization
Use memoization for expensive operations.
import { useMemo, useCallback, memo } from 'react';
import { allCountries, searchCountries } from 'countries-cities-ar';
// Memoized component
const CountryItem = memo(({ country, onClick }) => (
<div
onClick={() => onClick(country)}
className="p-2 hover:bg-gray-100 cursor-pointer"
>
<div className="font-medium">{country.nameAr}</div>
<div className="text-sm text-gray-600">{country.name}</div>
</div>
));
function OptimizedCountryList() {
const [search, setSearch] = useState('');
const [selected, setSelected] = useState(null);
// Memoize filtered results
const filteredCountries = useMemo(() => {
if (!search) return allCountries;
return searchCountries(search, 'ar');
}, [search]);
// Memoize callback
const handleSelect = useCallback((country) => {
setSelected(country);
console.log('Selected:', country.name);
}, []);
// Memoize stats calculation
const stats = useMemo(() => ({
total: filteredCountries.length,
totalCities: filteredCountries.reduce(
(acc, c) => acc + c.cities.length, 0
),
}), [filteredCountries]);
return (
<div>
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search..."
/>
<div className="text-sm text-gray-600 my-2">
Showing {stats.total} countries with {stats.totalCities} cities
</div>
<div className="grid grid-cols-2 gap-2">
{filteredCountries.map(country => (
<CountryItem
key={country.code}
country={country}
onClick={handleSelect}
/>
))}
</div>
</div>
);
}Form Integration
Integrate with React Hook Form for complex forms.
import { useForm, Controller } from 'react-hook-form';
import { allCountries } from 'countries-cities-ar';
function AddressForm() {
const { control, handleSubmit, watch, setValue } = useForm({
defaultValues: {
country: '',
city: '',
address: '',
}
});
const selectedCountryCode = watch('country');
const selectedCountry = allCountries.find(c => c.code === selectedCountryCode);
// Reset city when country changes
useEffect(() => {
setValue('city', '');
}, [selectedCountryCode, setValue]);
const onSubmit = (data) => {
console.log('Form data:', data);
};
return (
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
<Controller
name="country"
control={control}
rules={{ required: 'Country is required' }}
render={({ field, fieldState }) => (
<div>
<label>Country *</label>
<select {...field} className="w-full p-2 border rounded">
<option value="">Select Country</option>
{allCountries.map(c => (
<option key={c.code} value={c.code}>
{c.nameAr} - {c.name}
</option>
))}
</select>
{fieldState.error && (
<p className="text-red-500 text-sm">{fieldState.error.message}</p>
)}
</div>
)}
/>
{selectedCountry && (
<Controller
name="city"
control={control}
rules={{ required: 'City is required' }}
render={({ field, fieldState }) => (
<div>
<label>City/State *</label>
<select {...field} className="w-full p-2 border rounded">
<option value="">Select City</option>
{selectedCountry.cities.map((city, idx) => (
<option key={idx} value={idx}>
{city.nameAr || city.name}
</option>
))}
</select>
{fieldState.error && (
<p className="text-red-500 text-sm">{fieldState.error.message}</p>
)}
</div>
)}
/>
)}
<Controller
name="address"
control={control}
render={({ field }) => (
<div>
<label>Street Address</label>
<input
{...field}
type="text"
className="w-full p-2 border rounded"
/>
</div>
)}
/>
<button
type="submit"
className="px-4 py-2 bg-blue-500 text-white rounded"
>
Submit
</button>
</form>
);
}