反应本机,状态更改,但组件无法正确渲染

时间:2018-10-17 12:34:46

标签: reactjs react-native

我正在开发我的第一个React Native应用程序,但是对React和React Native感到非常满意,这让我感到惊讶。

目标-允许用户根据其输入需求动态创建选项卡。每个选项卡都重复使用作为表单的相同组件。按下时,选项卡应显示其对应的表格。表格工作正常。

问题-按下Tab键时,父组件将无法呈现正确的表单。状态会更新,但组件仍保留在所选的第一个组件上。如果我在一个屏幕上一个接一个地列出表单,我可以看到填写一个表单对其他表单没有影响(期望的效果)。

如果我不渲染表单组件,它将在第一次按Tab键时起作用。这使我想知道React是否不在父组件中注册更改,因为子组件始终是我希望显示的其他子组件的副本。

我没有运气就以三种方式解决了这个问题。

  1. 创建一个以父组件状态存储的组件数组。创建一个新的选项卡可以通过抓住一个数组,将一个组件推入该组件并使用该新数组重置状态来将表单组件推入当前数组。我将按键存储在屏幕上更新的状态中。该键与组件数组中的索引匹配,以显示选定的组件及其相应的选项卡。

  2. 使用componentDidUpdate来设置屏幕上显示的组件,与上面类似,但不是在我的渲染函数中键入数组,而是在componentDidUpdate函数中手动设置组件的每次更新的displayView并使用在渲染。

  3. 当前(随后的代码)-为添加的每个选项卡在状态下创建唯一键,该选项卡存储了相应的组件,并使用该键来解密要显示的组件。

我决定在一些子组件上添加引用。我在渲染之前使用console.log查看是否选择了正确的组件进行显示。它显示了,但是没有以这种方式出现在屏幕上。我还向用户界面添加了被单击的选项卡编号,每次按选项卡时,我都可以看到状态正确更新。

任何帮助将不胜感激。不得已时,我要让用户在到达此视图之前选择所需的表单数量并根据该数量创建它,但我不希望这样做。

import React from 'react';
import { connect } from 'react-redux';
import { View, Text, TouchableOpacity } from 'react-native';
import CreateWorkoutSet from './CreateWorkoutSet';
import { Entypo } from '@expo/vector-icons';

class CreateWorkout extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      workoutSetTemplate0: <CreateWorkoutSet navigation={this.props.navigation}/>,
      showTab: 0,
      totalTabs: 0,
    }

    this.addWorkoutSetToGroup = this.addWorkoutSetToGroup.bind(this)
  }

  componentDidMount() {
    this.setState({
      tabs: [
        <TouchableOpacity onPress={() => this.setState({ showTab: 0 })}>
          { this.state.showTab === 0 ? (
            <View style={{ backgroundColor: 'red', height: 40, width: 40 }}>
              <Text>Tab: 1</Text>
            </View>
          ) :
            <View style={{ backgroundColor: 'grey', height: 40, width: 40 }}>
              <Text>Tab: 1</Text>
            </View>
          }
        </TouchableOpacity>
      ],
      showTab: 0
    })
  }

  addWorkoutSetToGroup() {
    let tabNumber = this.state.totalTabs + 1 
    let tabKey = `workoutSetTemplate${tabNumber}` 
    let tabs = this.state.tabs 
    tabs.push(
      <TouchableOpacity onPress={() => this.setState({ showTab: tabNumber })}>
        { this.state.showTab === tabNumber ? (
          <View style={{ backgroundColor: 'red', height: 40, width: 40 }}>
            <Text>Tab: {tabNumber}</Text>
          </View>
        ) : 
          <View style={{ backgroundColor: 'grey', height: 40, width: 40 }}>
            <Text>Tab: {tabNumber}</Text>
          </View>
        }
      </TouchableOpacity>
    )
    this.setState({ [tabKey]: <CreateWorkoutSet navigation={this.props.navigation} />, tabs: tabs, totalTabs: tabNumber })
  }

  render() {
    let template = this.state[`workoutSetTemplate${this.state.showTab}`]
    let tabs = this.state.tabs
    return(
      <View style={{flex: 1, justifyContent: 'center', marginTop: 20}}>
        <View style={{ flexDirection: 'row' }}>
          {tabs}
        </View>
        <View>
          <Text>Add Exercise To Group</Text>
          <TouchableOpacity onPress={()=> this.addWorkoutSetToGroup()}>
            <Entypo name='circle-with-plus' size={36} color='red' />
          </TouchableOpacity>
        </View> 
        <TouchableOpacity onPress={() => this.props.navigation.navigate('BlockDetail')}>
          <Text>Blocks</Text>
        </TouchableOpacity>
        <Text>{this.state.showTab}</Text>
        {template}
      </View>
    )
  }
}

export default connect()(CreateWorkout)

1 个答案:

答案 0 :(得分:0)

尝试致电

this.forceUpdate()

更新状态后