0

我有一个视图,其中我正在从 React Native Elements动态添加输入组件。最终,我需要验证在 Input 中输入的文本,因此,现在,我正在尝试在onChangeText上将 errorMessage 属性从 false 更改为 true 。不幸的是,即使状态组件更改为 true,我也没有尝试更改 errorMessage。我有一个Snack,为了方便起见,我的代码如下:

import * as React from 'react'
import { ScrollView, StyleSheet, View } from 'react-native'
import { Button, Icon, Input, Text } from 'react-native-elements'
import * as Shortid from 'shortid'

export default class App extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      timeInputs: [],
      validities: []
    }

    this.addTimeInput = this.addTimeInput.bind(this)
    this.removeTimeInput = this.removeTimeInput.bind(this)
    this.mutateValidities = this.mutateValidities.bind(this)
  }

  componentDidMount () {
    this.addTimeInput()
  }

  addTimeInput () {
    const identifier = Shortid.generate()
    const timeInputs = this.state.timeInputs
    const validities = this.state.validities

    let isTimeValid = false
    let time = ''

    new Promise(
      (resolve, reject) => {
        resolve(
          validities.push(
            { id: identifier, value: isTimeValid }
          ),
          timeInputs.push(
            <View key = { identifier }>
              <View style = { styles.row }>
                <Input
                  errorMessage = {
                    this.state.validities.filter(
                      validity => validity.id !== identifier
                    ).value == true
                      ? 'Valid'
                      : 'Invalid'
                  }
                  errorStyle = { styles.error }
                  onChangeText = {
                    value => {
                      time = value
                      this.mutateValidities(identifier, true)
                      console.log('TIME ' + identifier + ': ' + time)
                    }
                  }
                  placeholder = 'HH:MM AM/PM'
                  ref = { React.createRef() }
                />
                <Icon
                  color = { colors.dark }
                  name = 'add-circle'
                  onPress = { () => this.addTimeInput() }
                  type = 'material'
                />
                <Icon
                  color = { colors.dark }
                  name = 'remove-circle'
                  onPress = {
                    () => {
                      if (this.state.timeInputs.length > 1) {
                        this.removeTimeInput(identifier)
                      } else {
                        console.log('LENGTH: ' + this.state.timeInputs.length)
                      }
                    }
                  }
                  type = 'material'
                />
              </View>
            </View>
          )
        )
      }
    )
      .then(
        this.setState(
          {
            timeInputs: timeInputs,
            validities: validities
          }
        )
      )
      .catch(
        (reason) => {
          console.log(
            'Failed to create time-input because of the following: ' + reason
          )
        }
      )
  }

  mutateValidities (key, value) {
    this.setState(
      {
        validities: this.state.validities.map(
          validity => validity.id === key
            ? {...validity, value: value}
            : validity
        )
      }
    )
  }

  removeTimeInput (key) {
    this.setState(
      {
        timeInputs: this.state.timeInputs.filter(
          timeInput => timeInput.key !== key
        ),
        validities: this.state.validities.filter(
          validity => validity.id !== key
        )
      }
    )
  }

  render () {
    return (
      <ScrollView contentContainerStyle = { styles.container }>
        <Text h4 style = { styles.title }>Time Inputs</Text>
        {
          this.state.timeInputs.map(
            (value) => { return value }
          )
        }
        <Button
          buttonStyle = { styles.button }
          onPress = {
            () => this.state.validities.map(
              validity => console.log(validity.id + validity.value)
            )
          }
          title = 'Log Validities'
        />
      </ScrollView>
    )
  }
}

const colors = {
  dark: 'steelblue',
  light: 'aliceblue',
  medium: 'lightsteelblue',
  error: 'firebrick'
}

const styles = StyleSheet.create(
  {
    button: {
      backgroundColor: colors.dark,
      margin: 5
    },
    container: {
      alignItems: 'center',
      backgroundColor: colors.light,
      flex: 1,
      justifyContent: 'center'
    },
    error: {
      color: colors.error,
      fontSize: 12,
      margin: 5
    },
    row: {
      alignItems: 'center',
      flexDirection: 'row',
      margin: 5,
      width: '80%'
    },
    title: {
      margin: 5
    }
  }
)

应归功于McGregor (2017) 让我走到了这一步,但我仍然陷入困境。

参考:

McGregor, L.(2017 年 10 月 2 日)在 ReactJS 中更新数组中的对象的最佳方法是什么?[堆栈溢出答案]。取自https://stackoverflow.com/a/46518653/6084947

4

1 回答 1

0

我相信我的问题是我试图触发嵌套太深的视图中的更改。即使假设 props 被正确传递,当 state 改变时视图也不会更新,因为 React 只比较 props 和 state。根据“The Power Of Not Mutating Data”(Facebook,2019)中提出的建议,我通过使文本输入成为一个完整的 React 组件来避免这些问题的浅层比较。我还应用了 React Redux 来管理中央存储中的状态,而不是来回传递 props,即使在抽象文本输入之后我也无法开始工作。

代码现在分布在太多不同的文件之间,无法在此处发布,但任何有兴趣的人都可以在GitHubSnack上查看。

参考:

Facebook。(2019)。优化性能 [文档]。取自https://reactjs.org/docs/optimizing-performance.html#the-power-of-not-mutating-data

于 2019-09-26T21:39:29.847 回答