Shopify/restyle 将变量值传递给子组件

问题描述 投票:0回答:2

如果这个问题已在其他地方得到回答,我们深表歉意。是否有类型安全的方法将变体信息传递给子组件?

我正在尝试使用页面中描述的 useRestyle 挂钩创建自定义 Button 组件https://shopify.github.io/restyle/fundamentals/components/custom-components。我有这个代码:

const Button = ({
  onPress,
  label,
  buttonType,
  variant,
  ...rest
}: Props) => {
  const props = useRestyle(restyleFunctions, {variant, ...rest});

我提取出了变体,但将其传递回 useRestyle,因为它需要第二个参数中的变体属性。但当我这样做时,我失去了类型安全性。

Eg: Button variant is 'primary' | 'secondary'. restyleFunctions shows the error:
The types of 'propertiesMap.variant' are incompatible between these types.
Type 'boolean | undefined' is not assignable to type 'boolean'.
Type 'undefined' is not assignable to type 'boolean'.ts(2345)

谢谢你。

reactjs typescript react-native shopify
2个回答
0
投票

我已经设法获得这样的值:

const {variant = 'primary'} = rest;
const props = useRestyle(restyleFunctions, rest)

必须传递默认值,因为变量是 Restyle 中的可选属性。


0
投票

这是我使用shopify restyle 的自定义按钮的方式

import React from 'react';
import {
  ActivityIndicator,
  Pressable,
  PressableProps,
  TextStyle,
} from 'react-native';
import {BorderProps, ColorProps, createBox, useTheme} from '@shopify/restyle';

import {Text} from './Text';
import {Theme} from '../config/theme';

const BaseButton = createBox<Theme, PressableProps>(Pressable);

type Props = React.ComponentProps<typeof BaseButton> &
  ColorProps<Theme> &
  BorderProps<Theme> & {
    label: string;
    outline?: boolean;
    loading?: boolean;
    textStyle?: TextStyle;
    textProps?: React.ComponentProps<typeof Text>;
    leftIcon?: React.ReactNode;
    rightIcon?: React.ReactNode;
    shadow?: boolean;
    color?: any;
  };

const Button = ({
  label,
  loading,
  backgroundColor,
  outline,
  shadow = true,
  color: textColor,
  ...props
}: Props) => {
  const theme = useTheme<Theme>();

  const color = outline ? backgroundColor : 'background';
  const bgColor = outline ? 'background' : backgroundColor;

  return (
    <BaseButton
      flexDirection="row"
      backgroundColor={props.disabled ? 'gray400' : bgColor}
      paddingHorizontal="xxl"
      paddingVertical={{phoneSm: 'xxs', phone: 'xxxs'}}
      borderRadius="s"
      borderWidth={outline ? 0.5 : 0}
      borderColor={props.disabled ? 'background' : color}
      justifyContent="center"
      alignItems="center"
      shadowOffset={{
        width: 0,
        height: 1,
      }}
      shadowOpacity={shadow ? 0.22 : 0}
      shadowRadius={2.22}
      elevation={shadow ? 3 : 0}
      {...props}
      onPress={e => !loading && props.onPress && props.onPress(e)}>
      {props.leftIcon && (
        <Text color={color} marginRight="xxs">
          {props.leftIcon}
        </Text>
      )}
      <Text
        variant="buttonLabel"
        color={props.disabled ? 'background' : textColor ? textColor : color}
        marginRight={loading ? 's' : undefined}
        fontSize={{phoneSm: 14, phone: 16}}
        {...props.textProps}>
        {label}
      </Text>
      {/* {props.rightIcon && (
        <Text color={color} marginLeft="xxs" {...props.textProps}>
          {props.rightIcon}
        </Text>
      )} */}
      {loading ? <ActivityIndicator color={theme.colors[color]} /> : null}
    </BaseButton>
  );
};

export default Button;
© www.soinside.com 2019 - 2024. All rights reserved.