Пользовательский реагирующий хук для динамической установки классов CSS - PullRequest
0 голосов
/ 27 июня 2019

Я сейчас играю и изучаю хиты React.Я хотел повторно использовать возможность установки тени элемента (используя bootstrap в качестве css-framework).

Вот как выглядит мой App:

export const App: React.FunctionComponent<IAppProps> = ({ }: IAppProps) => {
    // get shadow-classes for alert
    const [shadowClasses, setShadowClasses] = useShadow("none");

    // define callbacks when hovering the alert
    const handleMouseEnter = () => setShadowClasses("regular");
    const handleMouseOut = () => setShadowClasses("none");

    // return the markup to be used
    return (
        <Container>
            <Grid.Row>
                <Grid.Col>
                    <Alert color={Constants.Color.Danger} className={classNames(shadowClasses)} onMouseEnter={handleMouseEnter} onMouseOut={handleMouseOut} >{"This is some kind of an alert ..."}</Alert>
                </Grid.Col>
            </Grid.Row>
        </Container>
    );
}; 

Моя цель - добавить тень при Alert.К сожалению, ничего не происходит при наведении, и я не понимаю почему.

Ниже приведена реализация моей "пользовательской ловушки":

export function useShadow(initialType: "none"|"sm"|"regular"|"large"): [string[], (type: "none"|"sm"|"regular"|"large") => void] {
    // define the classes to be used
    const classNames: string[] = [];

    // get the shadow's current value
    const [shadowType, setShadow] = React.useState(initialType);

    // set depending on given type
    switch (shadowType) {
        case "none":
            classNames.push(`shadow-none`);
            break;
        case Constants.BreakpointSize.Small:
            classNames.push(`shadow-sm`);
            break;
        case "regular":
            classNames.push(`shadow`);
            break;
        case Constants.BreakpointSize.Large:
            classNames.push(`shadow-lg`);
            break;
    }

    // define the callback to change the shadow
    const handleChange = (type: Type) => () => setShadow(type);

    // return the class-names and the change-callback
    return [classNames, handleChange];
}

Я даже не уверен, правильно ли этоспособ использования пользовательских хуков или нет.

** Обновление **

Я создал хук useSpacing для установки расстояния между элементами, который реализован следующим образом:

export function useSpacing(initialSpacingProps: ISpacingProps[] = []): [string[], (spacingProps: ISpacingProps[]) => void] {
    // get the state-value
    const [spacingProps, setSpacingProps] = React.useState(initialSpacingProps);

    // create the result holding the class-names
    const spacingClasses: string[] = [];

    // loop through given spacing-definitions
    for (let spacingProp of spacingProps) {
        // get the values
        const { breakpoint, property, side, size, negative } = spacingProp;

        // handle depending on breakpoint
        spacingClasses.push(`${property}${side}${breakpoint !== Constants.BreakpointSize.ExtraSmall ? `-${breakpoint}` : ``}-${negative && size !== Size.Auto ? `n` : ``}${size}`);
    }

    // define the callback when the value should be changed
    const handleChange = (newSpacingProps: ISpacingProps[]) => setSpacingProps(newSpacingProps);

    // return the classes
    return [spacingClasses, handleChange];
}

и используется следующим образом:

export const App: React.FunctionComponent<IAppProps> = ({ }: IAppProps) => {
    const initialSpacingProps = [
        {
            breakpoint: Constants.BreakpointSize.ExtraSmall,
            property: Spacing.Property.Margin,
            side: Spacing.Side.LeftRight,
            size: Spacing.Size.Two
        }
    ];

    const clickedSpacingProps = [
        {
            breakpoint: Constants.BreakpointSize.Small,
            property: Spacing.Property.Padding,
            side: Spacing.Side.TopBottom,
            size: Spacing.Size.Five
        }
    ];

    // get the classes to apply spacing accordingly
    const [spacingClasses, setSpacingClasses] = useSpacing(initialSpacingProps);

    // define the callback when jumbotron gets clicked
    const handleClick = React.useCallback(() => setSpacingClasses(clickedSpacingProps), []);

    // return the markup to be used
    return (
        <Container>
            <Grid.Row>
                <Grid.Col>
                    <Shadows.Shadow type={Constants.BreakpointSize.Large}>
                        <Jumbotron className={classNames(spacingClasses)} onClick={handleClick}>
                            <h1 className="display-4">Hello, world!</h1>
                        </Jumbotron>
                    </Shadows.Shadow>
                </Grid.Col>
            </Grid.Row>
        </Container>
    );
};

При нажатии на элемент jumbotron новый интервал применяется правильно

1 Ответ

1 голос
/ 27 июня 2019

Ваша handleChange функция возвращает другую функцию, удаление второй функции исправит ее.

const handleChange = (type: Type) => setShadow(type);

Демо: https://codesandbox.io/s/youthful-gould-offv6

...