Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] - AUTOCOMPLETE_BUG_WITH_VALUE_ONINPUTCHANGE #3405

Open
peppe180902 opened this issue Jul 3, 2024 · 9 comments
Open

[BUG] - AUTOCOMPLETE_BUG_WITH_VALUE_ONINPUTCHANGE #3405

peppe180902 opened this issue Jul 3, 2024 · 9 comments
Assignees

Comments

@peppe180902
Copy link

peppe180902 commented Jul 3, 2024

NextUI Version

THIS IS THE SANDBOX LINK: sandbox-link

2.4.2

Describe the bug

Hi, I have 3 autocompletes that work in condition with each other.
Only if the first has been completed will the second be enabled and so on for the third, otherwise they will start with an isDisabled value.

The problem is that if I have completed all 3 fields, when I empty the second the third is automatically disabled because there is a condition that I inserted so if it is empty it cannot be enabled, at this point I put a another condition whereby if this is emptied the value of the third input must be reset in order to return everything to normal, however what happens is that visually the value that the user had entered remains but if I make a console.log I see that the true value it has been reset in this way all the input is buggy because the user sees value 4 instead it has been reset so it is 0.

I attach the code and video to show you:
`import React, { useEffect, useRef, useState } from "react";
import { Autocomplete, AutocompleteItem } from "@nextui-org/react";
import { civic } from "visure/data/geographic";

interface AutoCompleteCivicProps {
civicValue: number;
setCivicValue: React.Dispatch<React.SetStateAction>;
isDisabled?: boolean;
}

/*
ERROR: QUANDO IL L'ADDRESS VIENE SVUOTATO IL CIVICO SI SETTA A 0 MA NELL'INPUT COME VALORE VISIVO RIMANE IL PRECEDENTE
IN REALTà IL VALORE E' 0 MA VISIVAMENTE NON VIENE AGGIORNATO => CAPIRE IL PERCHE' E RISOLVERE
*/

export const AutoCompleteCivic: React.FC = ({ civicValue, setCivicValue, isDisabled }) => {
const [touched, setTouched] = useState(false);
const [valid, setValid] = useState(false);
const inputRef = useRef(null);

const isValidCivic = (value: number) => {
    return civic.some(civicItem => civicItem.value === value);
};

const onInputChange = (value: string) => {
    setCivicValue(Number(value))
    setValid(isValidCivic(Number(value)));
};

const onClose = () => {
    setTouched(true);
    setValid(isValidCivic(civicValue));
};

useEffect(() => {
    if (civicValue === 0 && inputRef.current) {
        inputRef.current.value = ''; // Clear the input visually
    }
}, [civicValue]);

console.log('civicValueInsideAutoComplete', civicValue)

return (
    <Autocomplete
        classNames={{
            base: 'w-full',
            listbox: 'w-full',
        }}
        label="Cerca il civico..."
        variant="bordered"
        defaultItems={civic}
        //key={civicValue}
        value={civicValue}
        isDisabled={isDisabled}
        onInputChange={onInputChange}
        onClose={onClose}
        color={valid ? 'success' : 'default'}
        listboxProps={{
            emptyContent: 'Nessun civico trovato',
        }}
    >
        {(item) => <AutocompleteItem key={item.value}>{item.label}</AutocompleteItem>}
    </Autocomplete>
);

}`

Your Example Website or App

No response

Steps to Reproduce the Bug or Issue

i have reported everitingh in my screen video

Expected behavior

Input clear when is disabled

Screenshots or Videos

Registrazione.schermo.2024-07-03.alle.15.34.57.mov

Operating System Version

macOs

Browser

Chrome

@wingkwong
Copy link
Member

please provide a minimal reproducible example (e.g stackblitz).

@peppe180902
Copy link
Author

please provide a minimal reproducible example (e.g stackblitz).

how to do it?

@abhinandan-verma
Copy link
Contributor

abhinandan-verma commented Jul 3, 2024

@peppe180902 you can go to

https://codesandbox.io/p/devbox/funny-archimedes-ht3dtn?file=%2FApp.jsx&utm_medium=sandpack
use sandbox
It is just like a virtual VS code
Put you necessary code (demo) here to show the bug and then share the link of that project showing bug.

I hope you find it helpful :)

@peppe180902
Copy link
Author

peppe180902 commented Jul 4, 2024

@peppe180902 you can go to

https://codesandbox.io/p/devbox/funny-archimedes-ht3dtn?file=%2FApp.jsx&utm_medium=sandpack use sandbox It is just like a virtual VS code Put you necessary code (demo) here to show the bug and then share the link of that project showing bug.

I hope you find it helpful :)

this is the sandbox please help me:
https://codesandbox.io/p/devbox/ecstatic-yalow-hzcjt9

@abhinandan-verma
Copy link
Contributor

abhinandan-verma commented Jul 6, 2024

@wingkwong I have reproduces the bug, as per the provided reference and I want to work on it.
Should I continue ?

@abhinandan-verma
Copy link
Contributor

@peppe180902 The actual issue with your code is that it uses value & onValueChange props which are not actual InputProps (see here) in this file https://github.com/nextui-org/nextui/blob/canary/packages/components/autocomplete/src/use-autocomplete.ts

Screenshot 2024-07-07 at 5 28 50 PM

So you can use selectedKey and onSelectionChange props for changing the value of Text/value in Autocomplete.
Something like this

"use client";

import React, { useState } from "react";
import {
  Autocomplete,
  AutocompleteItem,
  Button,
  Input,
} from "@nextui-org/react";
import { Key } from "@react-types/shared";

import { animals } from "./data";

export default function App() {
  const [key, setKey] = useState<Key | null | undefined>(null);

  return (
    <div className="flex flex-col gap-10 p-3">
      <Autocomplete
        className="max-w-xs"
        defaultItems={animals}
        label="Favorite Animal, search for one"
        placeholder="Search an animal"
        selectedKey={key}
        onSelectionChange={(key) => setKey(key)}
      >
        {(animal) => (
          <AutocompleteItem key={animal.value}>{animal.label}</AutocompleteItem>
        )}
      </Autocomplete>
      
      <div className="flex flex-col gap-3">
        <h1>Selected key: {key}</h1>

        <Button onClick={() => setKey("")}>Clear Value</Button>
        <Button onClick={() => setKey("dog")}>Set Dog</Button>
        <Button onClick={() => setKey("cat")}>Set Cat</Button>
        <Button onClick={() => setKey("bird")}>Set Bird</Button>
      </div>

      <Input
        placeholder="Type a value"
        value={key?.toString()}
        onValueChange={(value) => setKey(value)}
      />
    </div>
  );
}

This will resolve your issue :)

@wingkwong is this workaround ok, OR I should work towards making the use of value Props possible for changing the value inside autocomplete ?
So in that case, value prop will be brought in use removing it from Omit which need to handled carefully in case of multi-selections.

@wingkwong
Copy link
Member

@abhinandan-verma

The actual issue with your code is that it uses value & onValueChange props

where does it use onValueChange in the sandbox code?

Also the issue (as shown in the video) is that the third autocomplete value got reset after cleaning the second one. Based on your statement, it doesn't explain anything and I don't know why Input component is here while the demo only contains 3 autocomplete components. You should fork the sandbox and modify on top of it to prove the proposed change s working.

@abhinandan-verma
Copy link
Contributor

Hey @peppe180902 I have debugged your issue now. I understand the delay but I was busy in some other works

I have simplified your logic in a single component, and it works completely fine the way you want it to work :)
Actually keys in autocomplete are controlled by selectedKey and onSelectionChange and not the value prop.
The following code implements the same logic and changes the state of consecutive Autocompletes in desired way

"use client";

import React, {  useEffect, useState } from "react";
import { Autocomplete, AutocompleteItem, Input } from "@nextui-org/react";

import { animalsData } from "./data";

type Key = string | number;

const TestTemplate = () => {
  const [addressKey, setAddressKey] = useState<Key>("");
  const [key, setKey] = useState<Key>("");
  const [civicKey, setCivicKey] = useState<Key>("");

  const [isVisibileAddress, setIsVisibleAddress] = useState<boolean>(false);
  const [isVisibleCivic, setIsVisibleCivic] = useState<boolean>(false);

  const checkCityKey = (value: Key) => {
    return animalsData.some((cityItem) => cityItem.value === value);
  };

  const checkCAddressKey = (value: Key) => {
    return animalsData.some((cityItem) => cityItem.value === value);
  }

  useEffect(() => {
    if (checkCityKey(key)) {
      setIsVisibleAddress(true);
    } else {
      setIsVisibleAddress(false);
      setAddressKey("");
    }

    if(checkCAddressKey(addressKey)) {
      setIsVisibleCivic(true);
    } else {
      setIsVisibleCivic(false);
      setCivicKey("");
    }
  }, [key, addressKey]);

  return (
    <div className="flex flex-col gap-4 w-[500px]">
      <Autocomplete
        className="max-w-xs"
        defaultItems={animalsData}
        label="Favorite Animal, search for one"
        placeholder="Search an animal"
        selectedKey={key}
        onSelectionChange={(key) => setKey(key as Key)}
      >
        {(animal) => (
          <AutocompleteItem key={animal.value}>{animal.label}</AutocompleteItem>
        )}
      </Autocomplete>

      <Autocomplete
        className="max-w-xs"
        defaultItems={animalsData}
        isDisabled={!isVisibileAddress}
        label="Favorite Animal, search for one"
        placeholder="Search an animal"
        selectedKey={addressKey}
        onSelectionChange={(key) => setAddressKey(key as Key)}
      >
        {(animal) => (
          <AutocompleteItem key={animal.value}>{animal.label}</AutocompleteItem>
        )}
      </Autocomplete>

      <Autocomplete
        className="max-w-xs"
        defaultItems={animalsData}
        isDisabled={!isVisibleCivic}
        label="Favorite Animal, search for one"
        placeholder="Search an animal"
        selectedKey={civicKey}
        onSelectionChange={(key) => setCivicKey(key as Key)}
      >
        {(animal) => (
          <AutocompleteItem key={animal.value}>{animal.label}</AutocompleteItem>
        )}
      </Autocomplete>


      <div className="flex flex-col gap-3 bg-secondary-200/40 p-4">
        <h4>Selected City key: {key}</h4>
        <h4>Selected Address key: {addressKey}</h4>
        <h4>Selected Civic key: {civicKey}</h4>
      </div>
      <div className="flex flex-col gap-3 bg-success-200/40 p-4">
        <h3>Is visible address: {isVisibileAddress.toString()}</h3>
        <h3>Is visible civic: {isVisibleCivic.toString()}</h3>
      </div>
    </div>
  );
};

export default TestTemplate;

data.ts

export type Animal = {
  label: string;
  value: string;
  description?: string;
};

export const animalsData: Animal[] = [
  {
    label: "Cat",
    value: "cat",
    description: "The second most popular pet in the world",
  },
  {
    label: "Dog",
    value: "dog",
    description: "The most popular pet in the world",
  },
  {
    label: "Elephant",
    value: "elephant",
    description: "The largest land animal",
  },
  { label: "Lion", value: "lion", description: "The king of the jungle" },
  { label: "Tiger", value: "tiger", description: "The largest cat species" },
  {
    label: "Giraffe",
    value: "giraffe",
    description: "The tallest land animal",
  },
  {
    label: "Dolphin",
    value: "dolphin",
    description: "A widely distributed and diverse group of aquatic mammals",
  },
  {
    label: "Penguin",
    value: "penguin",
    description: "A group of aquatic flightless birds",
  },
  {
    label: "Zebra",
    value: "zebra",
    description: "A several species of African equids",
  },
  {
    label: "Shark",
    value: "shark",
    description:
      "A group of elasmobranch fish characterized by a cartilaginous skeleton",
  },
  {
    label: "Whale",
    value: "whale",
    description: "Diverse group of fully aquatic placental marine mammals",
  },
  {
    label: "Otter",
    value: "otter",
    description: "A carnivorous mammal in the subfamily Lutrinae",
  },
  {
    label: "Crocodile",
    value: "crocodile",
    description: "A large semiaquatic reptile",
  },
];
autocomplete-solution.mov

I hope your problem will be solved now, feel free to ask if still any issue occurs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants