JedWatson / react-select

The Select Component for React.js
https://react-select.com/
MIT License
27.63k stars 4.13k forks source link

Error: `defaultStyles[key] is not a function` when adding a custom key to `styles` #5195

Open vasartam opened 2 years ago

vasartam commented 2 years ago

Good day.

I find it very convenient that I can place all the styles for Select component in the separate file and import them:

// index.js
import styles from './styles';

<Select
    styles={styles}
    // ...
/>

// styles.js
const styles = {
    control: (provided, state) => ({
        ...provided,
        // Control custom styles 
    }),
};

However, I have a fair amount of custom components, and I want them to share the same API for styles that react-select has. For that, I create a custom key in the styles object like so:

const styles = {
    control: (provided, state) => ({
        ...provided,
        // Control custom styles 
    }),
    checkbox: (provided, state) => ({
        ...provided,
        // Checkbox custom styles 
    }),
};

But when I start using that key inside a component, I get this error:

Uncaught TypeError: defaultStyles[key] is not a function

I use it like so:

export const Checkbox = ({ isChecked, isDisabled, ...props }) => {
    const { children, className, cx, getStyles, innerProps } = props;

    return (
        <div
            css={getStyles('checkbox', props)}
            className={cx(
                {
                    'checkbox': true,
                },
                className,
            )}
        >
            <IconCheckmark fill={isChecked ? 'white' : 'transparent'} css={{
                transition: transition,
            }}/>
        </div>
    );
};

The error is pointing to the line 1055 in the following code snippet: https://github.com/JedWatson/react-select/blob/ec3bd2eb7f5b10fa6ce3f9cac9d811a46a74f42a/packages/react-select/src/Select.tsx#L1051-L1059

Seems like react-select doesn't expect custom keys in styles parameter.

I've read the docs, and especially the Styles - cx and custom Components section, but that doesn't help to solve the problem.

Is there another way of writing custom styles to match the react-select API?

Thanks in advance.

Methuselah96 commented 2 years ago

Can you provide a CodeSandbox with your issue?

vasartam commented 2 years ago

@Methuselah96, sure. Don't mind if I would use CodePen?

Methuselah96 commented 2 years ago

Go for it.

vasartam commented 2 years ago

Ok, I got it, CodePen doesn't have a feature to create multiple files. Here is a CodeSandbox:

https://codesandbox.io/s/sleepy-cannon-pn0ulk

vasartam commented 2 years ago

For now it works if I declare a separate variable for styles and pass only the "state" props. Notice no provided parameter:

import React from 'react';
import { checkbox, iconCheckmark } from './styles';
import IconCheckmark from './checkmark.svg';

export const Checkbox = (props) => {
    return (
        <div css={checkbox(props)}>
            <IconCheckmark css={iconCheckmark(props)}/>
        </div>
    );
};

// styles.js
export const checkbox = (state) => {
    const { isChecked, isDisabled } = state;

    return {
        // styles
    }
};

export const iconCheckmark = (state) => {
    const { isChecked } = state;

    return {
        fill: isChecked ? 'white' : 'transparent',
    }
};

UPD: It might be that you need to install @emotion/css and setup it properly according to the guide on Object Styles.