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

问题描述:

Button组件一般由包含TouchableHighlight(或其他可触摸的)的Text元素组成。我正在尝试使用样式组件创建一个Button组件样式,但是难以让我的样式动态地响应道具。使用样式组件的React Native中的动态样式按钮

按钮组件

下面,我创建了一个Button组件类似的风格分量文档中发现的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> 

预期结果

所以,我希望我的按钮看起来像这样...

enter image description here

实际结果

但相反,它看起来像这样... enter image description here

我所做的解决至今

当我使用巡视react-devtools,我可以看到outline道具正在传递给Button组件。

enter image description here

但道具不向下传递给它的任何儿童

enter image description here

的文档状态的Passed Props部分,“病急乱投医组件传递他们的所有道具”,但我想不是一路下跌?

我的问题

什么我需要改变,这样我可以动态风格的基础上它的道具我的按钮?

这里有:

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

如果ButtonContainer是一个正常的阵营组成部分,你不会期望传递给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。你只需要将自己的道具传递给ButtonContainer以及Label

所以,你会你的代码改写为:

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

技术上一个阵营组件可以传下去道具到它的孩子,所以ButtonContainer使用React.ChildrenReact.cloneElement的API可以传递下来,Label。但ButtonContainer由于显而易见的原因没有这样做,例如你不希望underlayColoronPress自动传递到Label。这会造成很多令人困惑的错误。

+0

谢谢Satya!这一切都非常有意义。感谢您撰写了这样一个很好的解释,当然,它的工作原理与您描述的一样。 –

+0

要添加到@ satya164的答案,你可以立即继承像这样的所有道具:''。这样你就不需要手动添加你想传递的每一个新的道具。 –