algolia / autocomplete

🔮 Fast and full-featured autocomplete library
https://alg.li/autocomplete
MIT License
5.02k stars 330 forks source link

Next.js 13 with React 18 Render Error #1090

Open MichaelGorski opened 1 year ago

MichaelGorski commented 1 year ago

Description

Using autocomplete in NextJs 13 with the newest react 18 version is causing errors

Bildschirmfoto 2023-02-12 um 18 05 18

Reproduction

// using the default example from the api

import React, { useMemo } from "react"
import { createElement, Fragment, useEffect, useRef, useState } from "react"
import { render } from "react-dom"

import { usePagination, useSearchBox } from "react-instantsearch-hooks"
import { autocomplete, AutocompleteOptions } from "@algolia/autocomplete-js"
import { BaseItem } from "@algolia/autocomplete-core"
import { createLocalStorageRecentSearchesPlugin } from "@algolia/autocomplete-plugin-recent-searches"

import "@algolia/autocomplete-theme-classic"

type AutocompleteProps = Partial<AutocompleteOptions<BaseItem>> & {
  className?: string
}

type SetInstantSearchUiStateOptions = {
  query: string
}

export function Autocomplete({
  className,
  ...autocompleteProps
}: AutocompleteProps) {
  const autocompleteContainer = useRef<HTMLDivElement>(null)

  const { query, refine: setQuery } = useSearchBox()
  const { refine: setPage } = usePagination()

  const [instantSearchUiState, setInstantSearchUiState] =
    useState<SetInstantSearchUiStateOptions>({ query })

  const plugins = useMemo(() => {
    const recentSearches = createLocalStorageRecentSearchesPlugin({
      key: "instantsearch",
      limit: 5,
      transformSource({ source }) {
        return {
          ...source,
          onSelect({ item }) {
            setInstantSearchUiState({ query: item.label })
          },
        }
      },
    })

    return [recentSearches]
  }, [])

  useEffect(() => {
    setQuery(instantSearchUiState.query)
    setPage(0)
  }, [instantSearchUiState])

  useEffect(() => {
    if (!autocompleteContainer.current) {
      return
    }

    const autocompleteInstance = autocomplete({
      ...autocompleteProps,
      container: autocompleteContainer.current,
      initialState: { query },
      onReset() {
        setInstantSearchUiState({ query: "" })
      },
      onSubmit({ state }) {
        setInstantSearchUiState({ query: state.query })
      },
      onStateChange({ prevState, state }) {
        if (prevState.query !== state.query) {
          setInstantSearchUiState({
            query: state.query,
          })
        }
      },
      renderer: { createElement, Fragment, render },
      plugins,
    })

    return () => autocompleteInstance.destroy()
  }, [plugins])

  return <div className={className} ref={autocompleteContainer} />
}

Steps install latest next js 18 with src structure, not with app structure add autocomplete plugins

Expected behavior

shouldn't throw any errors only happens with autocomplete implemented

Environment

Haroenv commented 1 year ago

FYI, this is a warning, not an error. we have not yet updated the main example, but https://github.com/algolia/autocomplete/issues/950#issuecomment-1110688407 gives a user land solution

TylerAHolden commented 1 year ago

I was getting an actual error in next13 TypeError: Cannot add property __, object is not extensible and for anyone who is also getting this from trying to use custom templates that return jsx, the solution that worked for me was following the codebox example from https://github.com/algolia/autocomplete/issues/950#issuecomment-1110688407 (same as mentioned above) specifically the

  renderer: {
    createElement: React.createElement,
    Fragment: React.Fragment,
  },
  render({ children }, root) {
    if (!panelRoot.current) {
      panelRoot.current = createRoot(root);
    }

    panelRoot.current!.render(children);
  },

config options part is what resolved it for me.