🌈 react-select Cheatsheet Completo 🌈

react-select es un componente select totalmente personalizable y extensible para React. Proporciona funcionalidades avanzadas como búsqueda, selecciones múltiples, carga asíncrona de opciones, creación de nuevas opciones y una estilización flexible, todo ello con un enfoque en la accesibilidad.


1. 🌟 Conceptos Clave


2. 🛠️ Configuración Inicial

  1. Instalación:
    npm install react-select
    # o
    yarn add react-select
  2. Importación Básica:
    import Select from 'react-select';
    ```    *   Para funcionalidades avanzadas como Async o Creatable, se importan componentes específicos del mismo paquete.
    

3. 🚀 Uso Básico

3.1. Selector Estándar (Single Select)

import React, { useState } from 'react';
import Select from 'react-select';

const fruitOptions = [
  { value: 'apple', label: 'Manzana' },
  { value: 'banana', label: 'Plátano' },
  { value: 'orange', label: 'Naranja' },
];

function SingleSelectExample() {
  const [selectedFruit, setSelectedFruit] = useState(null); // El estado guarda el objeto completo de la opción

  const handleChange = (selectedOption) => {
    setSelectedFruit(selectedOption);
    console.log(`Opción seleccionada:`, selectedOption);
  };

  return (
    <div>
      <h3>Selector de Frutas</h3>
      <Select
        options={fruitOptions}
        onChange={handleChange}
        value={selectedFruit} // El valor del Select es el objeto de la opción
        placeholder="Selecciona una fruta..."
        isClearable // Permite borrar la selección
        isSearchable // Habilita la búsqueda
      />
      {selectedFruit && <p>Has seleccionado: {selectedFruit.label}</p>}
    </div>
  );
}

export default SingleSelectExample;

3.2. Selector Múltiple (Multi Select)

Simplemente añade la prop isMulti. onChange recibirá un array de objetos de opción.

import React, { useState } from 'react';
import Select from 'react-select';

const techOptions = [
  { value: 'react', label: 'React' },
  { value: 'vue', label: 'Vue.js' },
  { value: 'angular', label: 'Angular' },
  { value: 'node', label: 'Node.js' },
  { value: 'python', label: 'Python' },
];

function MultiSelectExample() {
  const [selectedTechs, setSelectedTechs] = useState([]); // El estado guarda un array de objetos de opción

  const handleChange = (selectedOptions) =&gt; {
    setSelectedTechs(selectedOptions || []); // selectedOptions puede ser null al borrar todo
    console.log(`Opciones seleccionadas:`, selectedOptions);
  };

  return (
    <div>
      <h3>Selector de Tecnologías</h3>
      <Select
        isMulti // ¡Esta prop lo convierte en multi-select!
        options={techOptions}
        onChange={handleChange}
        value={selectedTechs} // El valor es un array de objetos de opción
        placeholder="Selecciona tecnologías..."
        closeMenuOnSelect={false} // Mantener el menú abierto después de seleccionar en multi
      />
      {selectedTechs.length > 0 && (
        <p>Has seleccionado: {selectedTechs.map(tech =&gt; tech.label).join(', ')}</p>
      )}
    </div>
  );
}

exportquire MultipleSelectExample;

4. ⚙️ Props Comunes

Select es muy configurable a través de sus props.


5. 🚀 Funcionalidades Avanzadas

5.1. Selector Asíncrono (AsyncSelect)

Para cargar opciones desde una API o una fuente de datos remota.

import React, { useState } from 'react';
import AsyncSelect from 'react-select/async'; // Importa AsyncSelect

const loadUsers = async (inputValue) =&gt; {
  // Simula una API call
  const response = await new Promise(resolve =&gt; setTimeout(() =&gt; {
    const users = [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' },
      { id: 3, name: 'Charlie' },
    ];
    resolve(users.filter(user =&gt; user.name.toLowerCase().includes(inputValue.toLowerCase())));
  }, 500));

  return response.map(user =&gt; ({ value: user.id, label: user.name }));
};

function AsyncSelectExample() {
  const [selectedUser, setSelectedUser] = useState(null);

  return (
    <div>
      <h3>Buscador Asíncrono de Usuarios</h3>
      <AsyncSelect
        cacheOptions // Cachea las opciones cargadas
        loadOptions={loadUsers} // Función que carga las opciones
        defaultOptions // Carga las opciones por defecto al montar (si no quieres cargar solo al escribir)
        onChange={setSelectedUser}
        value={selectedUser}
        placeholder="Escribe para buscar usuarios..."
      />
    </div>
  );
}

export default AsyncSelectExample;

5.2. Selector “Creatable” (CreatableSelect)

Permite al usuario seleccionar una opción existente o crear una nueva.

import React, { useState } from 'react';
import CreatableSelect from 'react-select/creatable'; // Importa CreatableSelect

const colorOptions = [
  { value: 'red', label: 'Rojo' },
  { value: 'blue', label: 'Azul' },
  { value: 'green', label: 'Verde' },
];

function CreatableSelectExample() {
  const [selectedColor, setSelectedColor] = useState(null);

  const handleCreate = (inputValue) =&gt; {
    // Lógica para añadir la nueva opción a tu fuente de datos
    console.log(`Creando nueva opción: ${inputValue}`);
    const newOption = { value: inputValue.toLowerCase(), label: inputValue };
    // Idealmente, aquí también actualizarías tu lista de 'options'
    setSelectedColor(newOption); // Selecciona la nueva opción creada
  };

  return (
    <div>
      <h3>Selector de Colores (Creatable)</h3>
      <CreatableSelect
        isClearable
        options={colorOptions}
        onChange={setSelectedColor}
        onCreateOption={handleCreate} // Función para crear nueva opción
        value={selectedColor}
        placeholder="Selecciona o crea un color..."
        formatCreateLabel={(inputValue) =&gt; `Crear "${inputValue}"`} // Personaliza el texto de creación
      />
    </div>
  );
}

export default CreatableSelectExample;

5.3. Opciones Agrupadas

const groupedOptions = [
  {
    label: 'Frutas',
    options: [
      { value: 'apple', label: 'Manzana' },
      { value: 'banana', label: 'Plátano' },
    ],
  },
  {
    label: 'Vegetales',
    options: [
      { value: 'carrot', label: 'Zanahoria' },
      { value: 'brocoli', label: 'Brócoli' },
    ],
  },
];

// Uso: <Select options={groupedOptions} ... />

6. 💅 Estilización

react-select es altamente estilizable.

6.1. Usando la Prop styles (CSS-in-JS)

Permite sobrescribir los estilos de los componentes internos.

const customStyles = {
  control: (baseStyles, state) =&gt; ({ // Estilos para el contenedor principal
    ...baseStyles,
    borderColor: state.isFocused ? 'blue' : '#ccc',
    boxShadow: state.isFocused ? '0 0 0 1px blue' : 'none',
    '&:hover': {
      borderColor: 'blue',
    },
    borderRadius: '8px',
    minHeight: '40px',
  }),
  option: (baseStyles, state) =&gt; ({ // Estilos para cada opción del menú
    ...baseStyles,
    backgroundColor: state.isFocused ? '#e0f2f7' : (state.isSelected ? '#b2e2f2' : 'white'),
    color: state.isSelected ? 'black' : 'inherit',
    cursor: 'pointer',
    '&:active': {
      backgroundColor: '#a0daed',
    },
    padding: '10px 12px',
  }),
  singleValue: (baseStyles) =&gt; ({ // Estilos para el valor seleccionado en un single select
    ...baseStyles,
    color: '#333',
    fontWeight: 'bold',
  }),
  multiValue: (baseStyles) =&gt; ({ // Estilos para cada 'tag' en un multi-select
    ...baseStyles,
    backgroundColor: '#e0e0e0',
    borderRadius: '4px',
  }),
  multiValueLabel: (baseStyles) =&gt; ({
    ...baseStyles,
    color: '#333',
  }),
  multiValueRemove: (baseStyles) =&gt; ({
    ...baseStyles,
    color: '#999',
    '&:hover': {
      backgroundColor: '#ff7878',
      color: 'white',
    },
  }),
  placeholder: (baseStyles) =&gt; ({
    ...baseStyles,
    color: '#aaa',
  }),
  menu: (baseStyles) =&gt; ({ // Estilos para el menú desplegable
    ...baseStyles,
    borderRadius: '8px',
    boxShadow: '0 4px 8px rgba(0, 0, 0, 0.15)',
    zIndex: 9999, // Asegura que el menú esté por encima de otros elementos
  }),
  indicatorSeparator: (baseStyles) =&gt; ({ // Ocultar el separador de indicadores
    ...baseStyles,
    display: 'none',
  }),
  dropdownIndicator: (baseStyles, state) =&gt; ({ // Estilos para el icono de flecha
    ...baseStyles,
    color: state.isFocused ? 'blue' : '#ccc',
    transition: 'transform 0.2s ease-in-out',
    transform: state.menuIsOpen ? 'rotate(180deg)' : null,
  }),
};

// Uso: <Select styles={customStyles} ... />

6.2. Usando className y CSS (o Módulos CSS)

Aplica tus propias clases CSS a la envoltura principal.

// MySelect.module.css
.my-select-container .react-select__control {
  border: 2px solid purple;
  /* ... otros estilos */
}
.my-select-container .react-select__option--is-focused {
  background-color: lightgray;
}

// MyComponent.jsx
import styles from './MySelect.module.css';
<Select
  className={styles['my-select-container']}
  classNamePrefix="react-select" // Para que las clases internas sean react-select__control, etc.
  options={...}
  // ...
/>

7. ✍️ Integración con Formularios (ej. React Hook Form)

react-select es un componente controlado, por lo que necesita ser envuelto con el Controller de React Hook Form para su correcta integración.

import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import Select from 'react-select';

const options = [
  { value: 'apple', label: 'Manzana' },
  { value: 'banana', label: 'Plátano' },
];

function FormWithReactSelect() {
  const { control, handleSubmit, formState: { errors } } = useForm({
    defaultValues: {
      fruit: null, // Valor inicial para el select
    }
  });

  const onSubmit = (data) =&gt; {
    console.log('Datos del formulario:', data);
    // data.fruit contendrá el objeto de la opción seleccionada (o null)
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label>
        Selecciona una fruta:
        <Controller
          name="fruit" // Nombre del campo en el formulario
          control={control} // Instancia de control de React Hook Form
          rules={{ required: '¡Este campo es obligatorio!' }} // Reglas de validación
          render={({ field }) =&gt; ( // 'field' contiene props { onChange, onBlur, value, name, ref }
            <Select
              {...field} // Pasa todas las props de `field` (onChange, onBlur, value, etc.)
              options={options}
              isClearable
              placeholder="Elige una fruta..."
            />
          )}
        />
        {errors.fruit && <p style={{ color: 'red' }}>{errors.fruit.message}</p>}
      </label>
      <br />
      <button type="submit">Enviar Formulario</button>
    </form>
  );
}

export default FormWithReactSelect;

8. 💡 Buenas Prácticas y Consejos


Este cheatsheet te proporciona una referencia completa de react-select, cubriendo sus conceptos esenciales, uso básico, funcionalidades avanzadas, estilización y las mejores prácticas para integrarlo en tus aplicaciones React.