【问题标题】:React Native Dynamic StylingReact Native 动态样式
【发布时间】:2019-01-20 04:51:42
【问题描述】:

我正在创建一个加密应用程序,我想在价格下跌时将背景颜色更改为红色,在价格上涨时将背景颜色更改为绿色,然后在 2 秒后使用 setTimeout 将背景更改为正常。

我尝试了两种不同的方法来至少改变背景颜色,但在这两种情况下我都得到了以下错误

您尝试将键 backgroundColor 设置为 #ffe5e5 在一个本来是不可变的并且已被冻结的对象上。

我询问了separate question for the same,但由于某种原因,我收到的回复并不令人信服。

后记,我尝试了一种不同的方法(不允许使用 StyleSheet 的方法),但我仍然遇到同样的错误。

我把我的新代码放在这里(你可以从问题中参考我以前的代码)

首先我在这样的全局范围内声明了一个对象

var upperRow = {
    display: "flex",
    flexDirection: "row",
    marginBottom: 5, 
    backgroundColor: "white"
} 


class  CoinCard extends Component {

然后我尝试像这样更改背景颜色

  componentWillReceiveProps(nextProps) {

    if (this.props.coinPrice != nextProps.coinPrice ) {
       if (this.props.coinPrice > nextProps.coinPrice) {

           upperRow["backgroundColor"] = "#ffe5e5";
 }
}

然后像这样分配样式

return (

    <View style={container}>

            <View style={upperRow}>

[问题:] 如何动态更改样式?

【问题讨论】:

  • 只是想知道,有什么理由它是CoinCard之外的变量吗?
  • @Dan 没有具体原因,可能是一种糟糕的编码习惯,试图让事情正常进行

标签: reactjs react-native


【解决方案1】:

无论您的硬币最近是否减少,您都需要保持状态。 想象一下这种形状的状态:

state = {
  hasIncreased: boolean,
  hasDecreased: boolean,
}

现在您可以在 componentWillReceiveProps 中更改此状态(虽然现在已弃用,因此如果您使用的是 16.3 或更高版本,可能会考虑逐步淘汰它),如下所示:

componentWillReceiveProps(nextProps) {
  if (nextProps.coinPrice < this.props.coinPrice)
    this.setState({hasDecreased: true, hasIncreased: false})

  if (nextProps.coinPrice > this.props.coinPrice)
    this.setState({hasIncreased: true, hasDecreased: false})
}

既然有了这个状态,就可以有条件地添加一些样式了:

render() {
  const {hasIncreased, hasDecreased} = this.state
  return (
    <View style={[ //styles can be an array!
      upperRow, 
      hasIncreased && {backgroundColor: 'green'},
      hasDecreased && {backgroundColor: 'red'},
    ]}/>
  )
}

现在剩下的就是在 2 秒后重置状态。对我来说,最好使用componentDidUpdate-lifecycle

componentDidUpdate(prevProps) {
  // only queue the reset if it's actually necessary, not on random updates
  if (prevProps.coinPrice !== this.props.coinPrice) {
    clearTimeout(this.timeout)
    // we need to be able to reset the timeout
    this.timeout = setTimeout(
      () => this.setState({hasDecreased: false, hasIncreased: false}),
      2000,
    )
  }
}

您应该尽量避免只是以可变的方式更改样式。重点是您的状态应该反映您所显示的内容。

【讨论】:

  • 优秀的答案,只有一件事我无法理解你在这里的意思upperRow, hasIncreased &amp;&amp; {backgroundColor: 'green'}, hasDecreased &amp;&amp; {backgroundColor: 'red'}, 就像hasIncreased &amp;&amp; {backgroundColor: 'green'}, hasDecreased &amp;&amp; {backgroundColor: 'red'}, 一样(这可能是一个三元表达式,但你为什么这样做&& {backgroundColor: 'red'}跨度>
  • 确实是三元表达式。我们要做的是,如果hasIncreased 为真,则返回包含绿色背景的样式。如果hasDecreased 为真,我们希望返回包含红色背景的样式。我喜欢为此使用三元组,因为它简洁并且对我来说仍然非常易读。由于style 属性也采用了一系列样式,因此至少对我来说这似乎是最简单的方法。
  • 谢谢冠军,即使我是三元表达式的忠实粉丝,但我总是认为我们需要为他们提供其他条件类似 this.state.increased ? {backgroundColor: "green"} : {backgroundColor: "white"}, 我的意思是这部分:{backgroundColor: "white"},
  • 是的。通常,如果您要使用这样的短手,您会使用condition ? if : else。我认为我错误地将其标记为三元表达式,而只是使用运算符。写value &amp;&amp; value2时,如果第一个值为真,则返回第二个,否则返回第一个。基本上,我使用&amp;&amp; 运算符(可以使用|| 进行逆运算)来获得更短的if 语句。如果它看起来有点陌生,请随意定义一个类方法,它可以使用成熟的if-statement 返回您需要的任何内容!
猜你喜欢
  • 2019-07-17
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
  • 2019-01-11
相关资源
最近更新 更多