【问题标题】:React Native Dynamically created components not rendering on first clickReact Native 动态创建的组件在第一次点击时不呈现
【发布时间】:2018-08-10 12:49:45
【问题描述】:

我正在尝试通过将列表项动态添加到 state 中的数组中来创建列表,然后使用 map 运算符对其进行迭代。但是,仅在第二次单击处理 setState 方法的按钮后才会呈现新的列表项。有解决这个问题的指点吗?

...
constructor(props) {
    super(props);
    this.state = {
        requirements:[], // Placeholder array in state
        currentRequirement
    }
}
...

在我的render 方法中,我有这个。

{
    this.state.requirements.map((el,i) => (
        <TouchableOpacity key={i}>
         <BulletItem text={el}/>
        </TouchableOpacity>
    ))
}
<FormInput 
    onChangeText={(value) => { 
        this.setState({ currentRequirement: value})}
    } 
    placeholder="Enter a new requirement"
/>

<Button 
    title="Add Requirement" 
    onPress={() => {
             this.onAddRequirementComponent()
    }}
/>

setState的处理方法是这样的。

onAddRequirementComponent() {
    this.setState(previousState => ({
        requirements: [...previousState.requirements, this.state.currentRequirement],
        currentRequirement:''
    }))
}

更新:完整组件

import React, { Component } from 'react';
import { Text, View, StyleSheet, ScrollView, Picker, TouchableOpacity } from 'react-native';
import { BulletItem, TagCloud } from "../components/index";
import { Actions } from "react-native-router-flux";
import {
    Button,
    Header,
    FormInput,
    FormLabel,
} from 'react-native-elements';
export default class ListScreen extends Component {

    constructor(props) {
        super(props);
        this.state = {
            jobtype: '',
            level: '',
            requirements: [],
            benefits: [],
            currentRequirement: '',
            currentBenefit: ''
        }
    }
    render() {
        return (
            <View style={styles.container}>
                <Header
                    backgroundColor='#fff'
                    borderBottomWidth={0}
                    leftComponent={{ icon: 'corner-up-left', color: '#333', type: 'feather', onPress: () => { Actions.pop() } }}
                    centerComponent={{ text: 'Create New Job', fontFamily: 'VarelaRound-Regular', style: { color: '#333', fontSize: 18 } }}
                    rightComponent={{ icon: 'options', color: '#333', type: 'simple-line-icon' }} />
                <ScrollView>
                    <FormLabel>Job Title</FormLabel>
                    <FormInput placeholder="e.g. Full Stack Javascript Developer"/>
                    <FormLabel >REQUIREMENTS</FormLabel>
                    {
                        this.state.requirements.map((el, i) => (
                            <TouchableOpacity key={i}><BulletItem containerStyle={{ backgroundColor: '#EFF0F2', borderRadius: 4 }} style={{ backgroundColor: '#EFF0F2' }} text={el} /></TouchableOpacity>
                        ))
                    }
                                <FormInput 
                    onChangeText={(value) => { 
                        this.setState({ currentRequirement: value})}
                    } 
                    placeholder="Enter a new requirement"
                />

                <Button 
                    title="Add Requirement" 
                    onPress={() => {
                            this.onAddRequirementComponent()
                    }}
                />
                    <FormLabel style={{ fontFamily: 'VarelaRound-Regular', color: '#333' }} labelStyle={{ fontFamily: 'VarelaRound-Regular', color: '#333' }}>BENEFITS</FormLabel>
                    {
                        this.state.benefits.map((el, i) => (
                            <TouchableOpacity key={i}><BulletItem text={el} /></TouchableOpacity>
                        ))
                    }
                    <FormInput value={this.state.currentBenefit} onChangeText={(value) => { this.setState({ currentBenefit: value }) }} placeholder="3 years experience developing Javascript apps" />
                    <Button title="Add" onPress={() => { this.onAddBenefitComponent() }}/>
                    <Picker selectedValue={this.state.jobtype}
                        style={{ height: 50, width: '100%', backgroundColor: '#EFF0F2' }}
                        onValueChange={(itemValue, itemIndex) => this.setState({ jobtype: itemValue })}>
                        <Picker.Item label="Full Time" value="fulltime" />
                        <Picker.Item label="Part Time" value="parttime" />
                        <Picker.Item label="Contract" value="contract" />
                        <Picker.Item label="Remote" value="remote" />
                    </Picker>
                    <Picker selectedValue={this.state.level}
                        style={{ height: 50, width: '100%', backgroundColor: '#EFF0F2' }}
                        onValueChange={(itemValue, itemIndex) => this.setState({ level: itemValue })}>
                        <Picker.Item label="Junior" value="junior" />
                        <Picker.Item label="Mid-Level" value="mid" />
                        <Picker.Item label="Management" value="management" />
                        <Picker.Item label="Senior" value="senior" />
                    </Picker>
                </ScrollView>
            </View>
        );
    }

    onAddRequirementComponent() {
        if (this.state.currentRequirement)
            this.setState(previousState => ({
                requirements: [...previousState.requirements, this.state.currentRequirement],
                currentRequirement: ''
            }))
    }

    onAddBenefitComponent() {
        this.setState(previousState => ({
            benefits: [...previousState.benefits, this.state.currentBenefit],
            currentBenefit: ''
        }))

    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
    }
});

【问题讨论】:

  • 如果您单击按钮两次,是否会呈现 2 个项目,或者是否需要单击 2 次才能将 1 个项目添加到数组中并重新呈现?
  • @Tholle 在第二次点击后只呈现一项
  • 好吧,这很令人沮丧。您的 setState 看起来是正确的。您可以使用previousState.currentRequirement,但这不是问题。 Button 组件是如何实现的?也许它在双击时使用了onPress 方法。
  • @Tholle 该按钮来自react-native-elements ui 库。我怀疑相同并将其更改为简单的Text,但仍然没有运气。我怀疑我的 Genymotion 模拟器滞后并在物理设备上运行它 - 也没有运气。
  • 好的。你能包括你的整个组件吗?可能还有其他微妙的事情发生。

标签: javascript reactjs react-native ecmascript-6


【解决方案1】:

这是核心逻辑部分,完美运行。我只使用了像TextInput 这样的原生元素。我所做的唯一更改是通过添加value={this.state.currentRequirement} 以及@Tholle 对使用previousState 的建议来完全控制TextInput

class Test extends Component {
  state = {
    requirements: [],
    currentRequirement: ''
  }

  onAddRequirementComponent() {
    this.setState(previousState => ({
      requirements: [...previousState.requirements, previousState.currentRequirement],
      currentRequirement:''
    }))
  }

  render() {
    return(
      <View>
        <TextInput onChangeText={(value) => { 
          this.setState({ currentRequirement: value})}
        }
        value={this.state.currentRequirement}
        />

        { this.state.requirements.map((el,i) => (
            <Text key={i}>{el}</Text>
        ))}

        <Button 
          title="Add Requirement" 
          onPress={() => {
            this.onAddRequirementComponent()
          }}
        />
      </View>
    );
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-10
    • 2020-01-03
    • 2021-05-12
    相关资源
    最近更新 更多