簡體   English   中英

自定義react-hook,用於動態設置CSS類

[英]Custom react-hook for dynamically setting css-classes

我目前正在玩和學習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>
    );
};

單擊巨型機元素時,正確應用了新的間距

您的handleChange函數將返回另一個函數,刪除第二個函數將對其進行修復。

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

演示: https//codesandbox.io/s/youthful-gould-offv6

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM