Copiar enlace

Pero antes de empezar, primero veamos que es react-select

¿Qué es React Select?

React Select es una biblioteca altamente versátil y ampliamente utilizada en el desarrollo de aplicaciones web con React, ademas de tambien poder ser usada por supuesto en frameworks basados en React como seria Nextjs.

React Select facilita la creación de selectores de elementos personalizados y altamente funcionales dentro de una aplicación. A diferencia de los elementos select nativos de HTML, React Select brinda a los desarrolladores un control total sobre la apariencia y funcionalidad de los componentes de selección, ademas que evita al desarrollador crear este componente desde cero en cada aplicacion.

React Select permite a los desarrolladores crear desplegables de selección de datos con características avanzadas, como búsqueda en tiempo real, filtrado, paginación y capacidad de etiquetado múltiple. Está diseñado para ser altamente personalizable y se integra fácilmente con otros componentes y bibliotecas de React, lo que lo convierte en una opción poderosa para mejorar la experiencia del usuario en aplicaciones web.

Entonces sabiendo que es React Select, vamos a crear un proyecto desde cero. De hecho para este tutorial estare usando Vitejs, como generador de proyectos, aunque esto tambien funciona con Nextjs perfectamente.

Instalación de React Select con Vite.js

Para comenzar a utilizar React Select en tu proyecto Vite.js, sigue estos pasos sencillos:

Primero Crear un proyecto Vite.js: Si aún no tienes un proyecto Vite.js en marcha, puedes crear uno utilizando la línea de comandos. Ejecuta el siguiente comando para generar un nuevo proyecto:

npm init vite@latest my-react-select-app --template react

Esto creará una nueva carpeta llamada my-react-select-app con una estructura de proyecto de React y configuración de Vite.js.

Recuerda quitar todos los estilos de los archivo src/App.css y el archivo src/index.css.

Luego sigue con la Instalación de React Select. Una vez que tienes tu proyecto Vite.js configurado, dirígete a la carpeta del proyecto en tu terminal y ejecuta el siguiente comando para instalar React Select y sus dependencias:

npm install react-select

Esto agregará React Select a tu proyecto y lo hará disponible para su uso.

Luego vamos a Importar React Select, Ahora puedes importar React Select en tus componentes de React donde desees utilizarlo. Por ejemplo:

import Select from "react-select";

export default function App() {
  return <Select />;
}

¡Listo! Ahora tienes React Select integrado en tu proyecto Vite.js y estás listo para crear selectores de elementos interactivos y personalizados en tus aplicaciones web.

Options de React Select

Creado el componente, ahora vamos a pasarle las opciones a React Select. Para esto podemos crear un arreglo de objetos, en donde cada objeto esta conformado por dos propiedades, una propiedad value y otra propiedad llamada label.

import Select from "react-select";

const options = [
  { value: "chocolate", label: "Chocolate" },
  { value: "strawberry", label: "Strawberry" },
  { value: "vanilla", label: "Vanilla" },
];

export default function App() {
  return <Select options={options} />;
}

onChange

Para capturar la selección de una opción en la lista desplegable, podemos utilizar el evento onChange de React Select de la siguiente manera:

<Select
  options={options}
  onChange={(selectedOption) => console.log(selectedOption)}
/>

El evento onChange se activa cuando el usuario elige una opción y proporciona la opción seleccionada como argumento, lo que nos permite realizar acciones específicas en función de la selección del usuario.

Multi Option en React Select

Para poder seleccionar multiples opciones desde el mismo Select basta con añadir la propiedad isMulti

export default function App() {
  return <Select isMulti options={options} />;
}

Por defecto, cuando seleccionamos una opción, el Select se cierra automáticamente. Si deseamos evitar este comportamiento y mantener el menú desplegado después de la selección, podemos utilizar la propiedad closeMenuOnSelect y establecerla en false, como se muestra a continuación:

<Select isMulti options={options} closeMenuOnSelect={false} />;

Además, tenemos la opción de asignar valores por defecto a las opciones seleccionadas proporcionando un array de objetos como valor inicial:

<Select
  isMulti
  options={options}
  closeMenuOnSelect={false}
  defaultValue={[options[1], options[2]]}
  onChange={(selectedOption) => console.log(selectedOption)}
/>

Es importante destacar que al seleccionar múltiples elementos, el evento onChange proporcionará un Array de JavaScript que contiene las opciones seleccionadas en lugar de un solo objeto.

Animated Components

Luego ademas de crear los componentes tambien podemos animarlos usando una característica mas de react-select:

import Select from "react-select";
import makeAnimated from "react-select/animated";

const options = [
  { value: "chocolate", label: "Chocolate" },
  { value: "strawberry", label: "Strawberry" },
  { value: "vanilla", label: "Vanilla" },
];

const animatedComponents = makeAnimated();

export default function App() {
  return (
    <Select
      isMulti
      options={options}
      components={animatedComponents}
      closeMenuOnSelect={false}
      defaultValue={[options[1], options[2]]}
    />
  );
}

Async Select

Cuando usamos react-select es posible que le pasemos datos que nuestra aplicacion ya posee quizas en un estado o un prop, pero hay veces que necesitamos obtener datos a medida que se necesiten, por ejemplo en un input de busqueda donde hay muchos datos y estos vienen del backend a medida que vamos tipeando.

import AsyncSelect from "react-select/async";

const options = [
  { value: "chocolate", label: "Chocolate" },
  { value: "cake", label: "Cake" },
  { value: "strawberry", label: "Strawberry" },
  { value: "vanilla", label: "Vanilla" },
];

const loadOptions = (
  searchValue: string,
  callback: (options: { value: string; label: string }[]) => void
) => {
  setTimeout(() => {
    const filteredOptions = options.filter((option) =>
      option.label.toLowerCase().includes(searchValue.toLowerCase())
    );
    callback(filteredOptions);
  }, 2000);
};

export default function App() {
  return (
    <AsyncSelect
      loadOptions={loadOptions}
      onChange={(selectedOption) => console.log(selectedOption)}
    />
  );
}

O tambien podemos cargar los datos al iniciar el componente y tener toda la lista disponible:

<AsyncSelect
  loadOptions={loadOptions}
  defaultOptions
  onChange={(selectedOption) => console.log(selectedOption)}
/>

Y esto tambien funciona usando isMulti:

<AsyncSelect
  loadOptions={loadOptions}
  defaultOptions
  onChange={(selectedOption) => console.log(selectedOption)}
  isMulti
/>

Estilos en React Select

Para añadir estilos tambien podemos hacerlo usando un prop llamado styles:

import AsyncSelect from "react-select/async";
import { StylesConfig } from "react-select";

interface Option {
  value: string;
  label: string;
  color: string;
}

const options = [
  { value: "chocolate", label: "Chocolate", color: "brown" },
  { value: "strawberry", label: "Strawberry", color: "red" },
  { value: "vanilla", label: "Vanilla", color: "white" },
  { value: "cake", label: "Cake", color: "yellow" },
];

const loadOptions = (
  searchValue: string,
  callback: (options: Option[]) => void
) => {
  setTimeout(() => {
    const filteredOptions = options.filter((option) =>
      option.label.toLowerCase().includes(searchValue.toLowerCase())
    );
    callback(filteredOptions);
  }, 2000);
};

const colorStyles: StylesConfig<Option> = {
  control: (styles) => ({ ...styles, backgroundColor: "#EEE0CB" }),
  option: (styles, { data, isDisabled, isFocused, isSelected }) => {
    console.log(styles, data, isDisabled, isFocused, isSelected);
    return {
      ...styles,
      background: "#EEE0CB",
      color: data.color,
    };
  },
};

export default function App() {
  return (
    <AsyncSelect
      loadOptions={loadOptions}
      defaultOptions
      styles={colorStyles}
      onChange={(selectedOption) => console.log(selectedOption)}
      // isMulti
    />
  );
}

Esto es otro ejemplo basado en la documnetacion mas completo en donde tambien añade un circulo dentro del select basado en el color:

import Select, { StylesConfig } from "react-select";
import chroma from "chroma-js";

interface ColourOption {
  value: string;
  label: string;
  color: string;
}

const options = [
  {
    value: "red",
    label: "Red",
    color: "#FF0000",
  },
  {
    value: "blue",
    label: "Blue",
    color: "#0000FF",
  },
  {
    value: "orange",
    label: "Orange",
    color: "#FFA500",
  }
];


const dot = (color = 'transparent') => ({
  alignItems: 'center',
  display: 'flex',

  ':before': {
    backgroundColor: color,
    borderRadius: 10,
    content: '" "',
    display: 'block',
    marginRight: 8,
    height: 10,
    width: 10,
  },
});

const colourStyles: StylesConfig<ColourOption> = {
  control: (styles) => ({
    ...styles,
    background: "#EEE0CB",
    color: "#fff",
  }),
  option: (styles, { data, isDisabled, isFocused, isSelected }) => {
    const color = chroma(data.color);
    return {
      ...styles,
      backgroundColor: isDisabled
        ? undefined
        : isSelected
        ? data.color
        : isFocused
        ? color.alpha(0.1).css()
        : undefined,
      color: isDisabled
        ? "#ccc"
        : isSelected
        ? chroma.contrast(color, "white") > 2
          ? "white"
          : "black"
        : data.color,
      cursor: isDisabled ? "not-allowed" : "default",

      ":active": {
        ...styles[":active"],
        backgroundColor: !isDisabled
          ? isSelected
            ? data.color
            : color.alpha(0.3).css()
          : undefined,
      },
    };
  },
    input: (styles) => ({ ...styles, ...dot() }),
  placeholder: (styles) => ({ ...styles, ...dot('#ccc') }),
  singleValue: (styles, { data }) => ({ ...styles, ...dot(data.color) })
};

export default function App() {
  return (
    <Select options={options} defaultValue={options[3]} styles={colourStyles} />
  );
}

Esto tambien funciona usando Opciones Multiples

const colorStyles: StylesConfig<Option> = {
  control: (styles) => ({ ...styles, backgroundColor: "#EEE0CB" }),
  option: (styles, { data, isDisabled, isFocused, isSelected }) => {
    console.log(styles, data, isDisabled, isFocused, isSelected);
    return {
      ...styles,
      background: "#EEE0CB",
      color: data.color,
    };
  },
  multiValue: (styles, { data }) => {
    return {
      ...styles,
      background: data.color,
      color: "#fff",
    };
  },
  multiValueLabel: (styles, { data }) => ({
    ...styles,
    color: "#fff",
  }),
  multiValueRemove: (styles, { data }) => ({
    ...styles,
    color: "#fff",
    cursor: "pointer",
    ":hover": {
      background: data.color,
      color: "#333",
    },
  }),
};

export default function App() {
  return (
    <AsyncSelect
      loadOptions={loadOptions}
      defaultOptions
      styles={colorStyles}
      onChange={(selectedOption) => console.log(selectedOption)}
      isMulti
    />
  );
}

Creatable

import { useState } from "react";
import CreatableSelect from "react-select/creatable";

interface Option {
  value: string;
  label: string;
  color: string;
}

const options = [
  { value: "chocolate", label: "Chocolate", color: "brown" },
  { value: "strawberry", label: "Strawberry", color: "red" },
  { value: "vanilla", label: "Vanilla", color: "white" },
  { value: "cake", label: "Cake", color: "orange" },
];

export default function App() {
  const [opts, setOpts] = useState<Option[]>(options);

  const handleInputChange = (inputValue: string, actionMeta: any) => {
    console.log("Input Changed");
    console.log(inputValue);
    console.log(actionMeta);
  };

  const handleCreate = (inputValue: string) => {
    console.log("Create Option");
    console.log(inputValue);
    const newOption = {
      value: inputValue.toLowerCase(),
      label: inputValue,
      color: "purple",
    };
    setOpts([...opts, newOption]);
  };

  return (
    <CreatableSelect
      options={opts}
      onChange={(selectedOption) => console.log(selectedOption)}
      onCreateOption={handleCreate}
      closeMenuOnSelect={false}
    />
  );
}
Actualizado por ultima vez el

Aprende a crear Select personalizados usando React Select, una biblioteca de npm altamente personalizable y fácil de integrar

¿Quieres Compatir mi Contenido?

Publicado:hace 4 años

Actualizado:hace un año