npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-autocomplete-france

v2.0.0

Published

React components for France Address Gouv Autocomplete

Downloads

92

Readme

react-autocomplete-france

Headless React hook for French address autocomplete powered by the Géoplateforme API.

Zero UI opinions — bring your own components, styles and UI kit (MUI, Ant Design, shadcn/ui, Mantine, Tailwind, plain HTML...).

Exemple

Installation

npm install react-autocomplete-france

Peer dependencies: react >= 18.2.0

Quick start

import { useAutocomplete } from 'react-autocomplete-france'

function AddressInput() {
  const { query, setQuery, suggestions, isLoading, isOpen, selectSuggestion } = useAutocomplete({
    onSelect: (suggestion) => {
      console.log(suggestion.properties.label)
      console.log(suggestion.geometry.coordinates) // [lon, lat]
    },
  })

  return (
    <div style={{ position: 'relative' }}>
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Rechercher une adresse..."
      />
      {isOpen && (
        <ul>
          {isLoading ? (
            <li>Chargement...</li>
          ) : (
            suggestions.map((s) => (
              <li key={s.properties.id} onClick={() => selectSuggestion(s)}>
                {s.properties.label}
              </li>
            ))
          )}
        </ul>
      )}
    </div>
  )
}

API Reference

useAutocomplete(options?)

Headless hook — returns state and handlers, renders nothing.

Options

| Prop | Type | Default | Description | |------|------|---------|-------------| | onSelect | (suggestion: AutocompleteFeature) => void | — | Called when a suggestion is selected | | debounce | number | 300 | Debounce delay in ms | | limit | number | 5 | Max number of results | | searchParams | Partial<AutocompleteQueryParams> | — | Additional API params (postcode, type, city, citycode...) | | baseURL | string | https://data.geopf.fr/geocodage | Custom API base URL (e.g. your own proxy) |

Return value

| Property | Type | Description | |----------|------|-------------| | query | string | Current search query | | setQuery | (value: string) => void | Update the search query (bind to your input's onChange) | | suggestions | AutocompleteFeature[] | List of address suggestions | | isLoading | boolean | Whether the API request is in progress | | isOpen | boolean | Whether the suggestions list should be shown | | selectSuggestion | (suggestion: AutocompleteFeature) => void | Select a suggestion (updates query, clears list, calls onSelect) | | clear | () => void | Clear query and suggestions |

Examples

With Material UI (MUI)

import { TextField, List, ListItemButton, ListItemText, Paper, CircularProgress } from '@mui/material'
import { useAutocomplete } from 'react-autocomplete-france'

function MUIAddressInput() {
  const { query, setQuery, suggestions, isLoading, isOpen, selectSuggestion } = useAutocomplete({
    onSelect: (s) => console.log(s),
  })

  return (
    <div style={{ position: 'relative' }}>
      <TextField
        fullWidth
        label="Adresse"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        slotProps={{
          input: {
            endAdornment: isLoading ? <CircularProgress size={20} /> : null,
          },
        }}
      />
      {isOpen && (
        <Paper sx={{ position: 'absolute', zIndex: 10, width: '100%', mt: 0.5 }}>
          <List dense>
            {suggestions.map((s) => (
              <ListItemButton key={s.properties.id} onClick={() => selectSuggestion(s)}>
                <ListItemText primary={s.properties.label} secondary={s.properties.context} />
              </ListItemButton>
            ))}
          </List>
        </Paper>
      )}
    </div>
  )
}

With Ant Design

import { Input, List, Spin } from 'antd'
import { useAutocomplete } from 'react-autocomplete-france'

function AntdAddressInput() {
  const { query, setQuery, suggestions, isLoading, isOpen, selectSuggestion } = useAutocomplete({
    onSelect: (s) => console.log(s),
  })

  return (
    <div style={{ position: 'relative' }}>
      <Input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Rechercher une adresse..."
        suffix={isLoading ? <Spin size="small" /> : null}
      />
      {isOpen && (
        <List
          style={{ position: 'absolute', zIndex: 10, width: '100%', background: '#fff' }}
          bordered
          size="small"
          dataSource={suggestions}
          renderItem={(s) => (
            <List.Item onClick={() => selectSuggestion(s)} style={{ cursor: 'pointer' }}>
              {s.properties.label}
            </List.Item>
          )}
        />
      )}
    </div>
  )
}

With Chakra UI v2

import { Box, Input, InputGroup, InputRightElement, List, ListItem, Spinner, Text } from '@chakra-ui/react'
import { useAutocomplete } from 'react-autocomplete-france'

function ChakraV2AddressInput() {
  const { query, setQuery, suggestions, isLoading, isOpen, selectSuggestion } = useAutocomplete({
    onSelect: (s) => console.log(s),
  })

  return (
    <Box position="relative">
      <InputGroup>
        <Input
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Rechercher une adresse..."
        />
        {isLoading && (
          <InputRightElement>
            <Spinner size="sm" />
          </InputRightElement>
        )}
      </InputGroup>
      {isOpen && (
        <List
          position="absolute"
          zIndex={10}
          width="100%"
          mt={1}
          bg="white"
          borderWidth="1px"
          borderRadius="md"
          boxShadow="md"
          maxH="250px"
          overflowY="auto"
        >
          {suggestions.map((s) => (
            <ListItem
              key={s.properties.id}
              px={4}
              py={2}
              cursor="pointer"
              _hover={{ bg: 'gray.100' }}
              borderBottomWidth="1px"
              onClick={() => selectSuggestion(s)}
            >
              <Text fontSize="sm" isTruncated>{s.properties.label}</Text>
              <Text fontSize="xs" color="gray.500">{s.properties.context}</Text>
            </ListItem>
          ))}
        </List>
      )}
    </Box>
  )
}

With Chakra UI v3

import { Box, Input, List, Spinner, Text, Group } from '@chakra-ui/react'
import { InputGroup } from '@chakra-ui/react/input-group'
import { useAutocomplete } from 'react-autocomplete-france'

function ChakraV3AddressInput() {
  const { query, setQuery, suggestions, isLoading, isOpen, selectSuggestion } = useAutocomplete({
    onSelect: (s) => console.log(s),
  })

  return (
    <Box position="relative">
      <InputGroup endElement={isLoading ? <Spinner size="sm" /> : undefined}>
        <Input
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Rechercher une adresse..."
        />
      </InputGroup>
      {isOpen && (
        <List.Root
          position="absolute"
          zIndex={10}
          width="100%"
          mt={1}
          bg="white"
          borderWidth="1px"
          borderRadius="md"
          boxShadow="md"
          maxH="250px"
          overflowY="auto"
          listStyle="none"
        >
          {suggestions.map((s) => (
            <List.Item
              key={s.properties.id}
              px={4}
              py={2}
              cursor="pointer"
              _hover={{ bg: 'gray.100' }}
              borderBottomWidth="1px"
              onClick={() => selectSuggestion(s)}
            >
              <Text fontSize="sm" truncate>{s.properties.label}</Text>
              <Text fontSize="xs" color="fg.muted">{s.properties.context}</Text>
            </List.Item>
          ))}
        </List.Root>
      )}
    </Box>
  )
}

With Tailwind CSS

import { useAutocomplete } from 'react-autocomplete-france'

function TailwindAddressInput() {
  const { query, setQuery, suggestions, isLoading, isOpen, selectSuggestion } = useAutocomplete({
    onSelect: (s) => console.log(s),
  })

  return (
    <div className="relative w-full max-w-md">
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Rechercher une adresse..."
        className="w-full rounded-lg border border-gray-300 px-4 py-2 focus:border-blue-500 focus:outline-none"
      />
      {isOpen && (
        <ul className="absolute z-10 mt-1 w-full max-h-60 overflow-auto rounded-lg border border-gray-200 bg-white shadow-lg">
          {isLoading ? (
            <li className="px-4 py-2 text-center text-gray-500">Chargement...</li>
          ) : (
            suggestions.map((s) => (
              <li
                key={s.properties.id}
                onClick={() => selectSuggestion(s)}
                className="cursor-pointer truncate px-4 py-2 hover:bg-blue-50"
              >
                <span className="font-medium">{s.properties.name}</span>
                <span className="ml-2 text-sm text-gray-500">{s.properties.context}</span>
              </li>
            ))
          )}
        </ul>
      )}
    </div>
  )
}

Filtered search (streets only in a specific postcode)

const { query, setQuery, suggestions, isOpen, selectSuggestion } = useAutocomplete({
  searchParams: { type: 'street', postcode: '75001' },
  onSelect: (s) => console.log(s),
})

Direct API usage (without React)

import { AutocompleteAPI } from 'react-autocomplete-france'

const api = new AutocompleteAPI()
const results = await api.autocompleteAddress('10 rue de la paix', 5)
console.log(results.features)

// Advanced search
const results2 = await api.searchAddress({
  q: 'rue de la paix',
  type: 'street',
  postcode: '75002',
  limit: 3,
})

Types

All types are exported:

import type {
  AutocompleteFeature,
  AutocompleteProperties,
  AutocompleteGeometry,
  AutocompleteResponse,
  AutocompleteQueryParams,
  UseAutocompleteProps,
  UseAutocompleteReturn,
} from 'react-autocomplete-france'

AutocompleteFeature

interface AutocompleteFeature {
  type: string
  geometry: {
    type: string
    coordinates: number[] // [longitude, latitude]
  }
  properties: {
    label: string        // "10 Rue de la Paix 75002 Paris"
    score: number
    id: string
    name: string         // "10 Rue de la Paix"
    postcode: string     // "75002"
    citycode: string     // "75102"
    city: string         // "Paris"
    context: string      // "75, Paris, Île-de-France"
    type: string         // "housenumber" | "street" | "locality" | "municipality"
    importance: number
    street?: string
    housenumber?: string
    district?: string
    x: number
    y: number
  }
}

Migration from v1.x

Recommended: migrate to the headless hook

v2.0 adopts a headless pattern — the hook no longer renders any UI.

Before (v1):

import { useAutocomplete } from 'react-autocomplete-france'

const { ref } = useAutocomplete({
  onSuggestionSelected: (s) => console.log(s),
  containerStyle: { backgroundColor: 'white' },
  hasWatermark: true,
})

return <input ref={ref} />

After (v2):

import { useAutocomplete } from 'react-autocomplete-france'

const { query, setQuery, suggestions, isLoading, isOpen, selectSuggestion } = useAutocomplete({
  onSelect: (s) => console.log(s),
})

return (
  <div>
    <input value={query} onChange={(e) => setQuery(e.target.value)} />
    {isOpen && (
      <ul>
        {isLoading
          ? <li>Chargement...</li>
          : suggestions.map((s) => (
              <li key={s.properties.id} onClick={() => selectSuggestion(s)}>
                {s.properties.label}
              </li>
            ))
        }
      </ul>
    )}
  </div>
)

Changes summary

| v1 | v2 | |----|-----| | onSuggestionSelected | onSelect | | containerStyle, suggestionStyle, suggestionLabelStyle | Render your own UI | | hasWatermark | Add your own attribution | | alignementRef, containerPosition | Position your own dropdown | | Returns { ref } | Returns { query, setQuery, suggestions, isLoading, isOpen, selectSuggestion, clear } | | Default debounce 500ms | Default debounce 300ms | | — | New: searchParams for filtered searches | | — | New: baseURL for custom API endpoint | | — | New: AutocompleteAPI exported |

Deprecated: keep v1 behavior with useAutocompleteLegacy

If you can't migrate immediately, switch to useAutocompleteLegacy — a drop-in replacement with the exact same v1 API:

- import { useAutocomplete } from 'react-autocomplete-france'
+ import { useAutocompleteLegacy } from 'react-autocomplete-france'

- const { ref } = useAutocomplete({
+ const { ref } = useAutocompleteLegacy({
    onSuggestionSelected: (s) => console.log(s),
    containerStyle: { border: '1px solid red' },
    hasWatermark: true,
  })

Warning: useAutocompleteLegacy is deprecated and will be removed in the next major version. It renders its own UI via DOM portals and is not compatible with custom UI kits. Migrate to useAutocomplete when possible.

Contributing

You can contribute to this project by opening an issue or a pull request.

License

MIT