使用样式化组件在 React Native 中动态样式化按钮

Dynamically Styled Button in React Native using Styled Components

Button 组件通常由用 TouchableHighlight(或其他可触摸)包裹的 Text 元素组成。我正在尝试创建一个使用 styled-components 设置样式的 Button 组件,但我无法让我的样式动态响应道具。

按钮组件

下面,我创建了一个类似于 styled-component 文档中的 Adapting based on props 示例的 Button 组件。

import React from 'react';
import { Text, TouchableHighlight } from 'react-native';
import styled from 'styled-components/native';

const colors = {
    accent: '#911',
    highlight: '#D22',
    contrast: '#FFF',
}

const Label = styled.Text`
  color: ${props => !props.outline ? colors.contrast : colors.accent};
  font-weight: 700;
  align-self: center;
  padding: 10px;
`

const ButtonContainer = styled.TouchableHighlight`
  background-color: ${props => props.outline ? colors.contrast : colors.accent};
  width: 80%;
  margin-top: 5px;
  border-color: ${colors.accent};
  border-width: 2px;
`

const Button = (props) => {
    return (
        <ButtonContainer
            onPress={props.onPress}
            underlayColor={colors.highlight}
        >
            <Label>
                {props.children}
            </Label>
        </ButtonContainer>
    );
};

export default Button;

按钮用法

导入后,我正在使用这样的按钮...

    <Button
      outline
      onPress={() => console.log('pressed')}>
      Press Me!
    </Button>

预期结果

因此,我希望我的按钮看起来像这样...

实际结果

但它看起来像这样...

到目前为止我为解决问题所做的工作

当我使用 react-devtools 检查时,我可以看到 outline 属性正在传递给 Button 组件。

但是这个道具并没有传给它的任何一个 children

文档状态的 Passed Props 部分,"styled-components pass on all their props",但我想不是一直都这样吗?

我的问题

我需要更改什么才能根据 Button 的属性动态设置 Button 的样式?

这里有:

const Button = (props) => {
    return (
        <ButtonContainer underlayColor={colors.highlight}>
            <Label>
                {props.children}
            </Label>
        </ButtonContainer>
    );
};

如果 ButtonContainer 是一个普通的 React 组件,您不会期望传递给 Buttonprops 会自动传递给 ButtonContainer。你必须做 <ButtonContainer underlayColor={colors.highlight} {...props} /> 才能做到。

实际上 ButtonContainer 是一个普通的 React 组件,唯一的区别是你使用 HOC 预应用了一些样式。

此外,如果您将其脱糖为 React.createElement 调用,您会发现 props 无法自动传递,因为函数的参数不会自动传递给内部的函数调用它。

const Button = (props) => {
    return React.createElement(ButtonContainer, { underlayColor: colors.highlight }, ...);
};

这与 styled-components 无关。你只需要自己将 props 传递给 ButtonContainer,以及传递给 Label.

因此您需要将代码重写为:

const Button = (props) => {
    return (
        <ButtonContainer underlayColor={colors.highlight} onPress={props.onPress} outline={props.outline}>
            <Label outline={props.outline}>
                {props.children}
            </Label>
        </ButtonContainer>
    );
};

从技术上讲,React 组件可以将 props 传递给它的子组件,因此 ButtonContainer 可以使用 React.ChildrenReact.cloneElement API 将它们传递给 Label。但是 ButtonContainer 出于明显的原因不这样做,例如您不希望 underlayColoronPress 自动传递给 Label。这会导致很多令人困惑的错误。