使用样式化组件在 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 组件,您不会期望传递给 Button
的 props
会自动传递给 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.Children
和 React.cloneElement
API 将它们传递给 Label
。但是 ButtonContainer
出于明显的原因不这样做,例如您不希望 underlayColor
和 onPress
自动传递给 Label
。这会导致很多令人困惑的错误。
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 组件,您不会期望传递给 Button
的 props
会自动传递给 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.Children
和 React.cloneElement
API 将它们传递给 Label
。但是 ButtonContainer
出于明显的原因不这样做,例如您不希望 underlayColor
和 onPress
自动传递给 Label
。这会导致很多令人困惑的错误。