提问者:小点点

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


Button组件通常由Text元素组成,该元素用TouchableHighlight(或其他touchable)包装。我正在尝试创建一个使用styled-components样式的按钮组件,但是我的样式很难动态响应道具。

下面,我创建了一个按钮组件,类似于样式化组件文档中的Adapting based on props示例。

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进行检查时,我可以看到outling道具正在向下传递到button组件。

但这个道具不会传给它的任何一个孩子

文档的pass Props部分表示,“styled-components pass on all ther Props”,但我猜不是一直往下走?

我需要更改什么,以便我可以根据按钮的道具动态地设置按钮的样式?


共1个答案

匿名用户

这里有:

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

如果ButtonContainer是一个普通的React组件,则您不会期望传递给ButtonProps会自动传递给ButtonContainer。您必须执行来执行此操作。

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

此外,如果您将其转换为react.createElement调用,您可以看到props是不可能自动传递的,因为函数的参数不会自动传递给它内部的函数调用。

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

它并不是styled-components特有的。您只需将道具自己传给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组件可以向下传递道具给它的子组件,因此ButtonContainer可以使用React.ChildreReact.CloneElementAPI向下传递道具给Label。但是buttoncontainer由于明显的原因不会这样做,例如,您不希望underlayColoronpress自动传递给label。它会引起很多混乱的虫子。