我已经在 React native 中创建了动态表单,如果用户单击该按钮,则会显示一个按钮,它将在该按钮上方添加新表单。用户单击按钮的次数将添加该表格。我已经做到了,但是在文本更改期间遇到了问题。
问题是,当我开始输入表格时,它首先显示秒的值,然后变为空
下面是我的代码 我尝试过
import React, { PureComponent } from 'react'
import {
Text,
View,
TextInput
} from 'react-native'
import { TouchableOpacity } from 'react-native-gesture-handler';
export class IndentForm extends PureComponent {
constructor(props) {
super(props);
this.state = {
indents:[]
};
}
addInput(){
this.setState({ indents:[...this.state.indents, ""]})
}
onTextChange = (event, index) => {
const { indent } = event.nativeEvent;
this.state.indents[index] = indent
this.setState({indent})
}
render() {
return (
<View style={{flex:1}}>
{
this.state.indents.map((indent,index) => {
return(
<View key={index}>
<TextInput
name="indent"
style={{height: 40,backgroundColor: 'azure', fontSize: 20}}
placeholder="Type here to translate!"
value={indent}
onChange={(event)=> this.onTextChange(event,index)}
/>
</View>
)
})
}
<TouchableOpacity
style={{ height:30, width:70, backgroundColor:'blue'}}
onPress={this.addInput.bind(this)}>
<Text>Add Form</Text>
</TouchableOpacity>
</View>
)
}
}
export default IndentForm
答案 0 :(得分:1)
我已经检查了您的snack
,并进行了一些更改。这是最终的工作版本:
import React, { PureComponent } from 'react'
import {
Text,
View,
TextInput
} from 'react-native'
import { TouchableOpacity } from 'react-native-gesture-handler';
export class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
formFields:[{value: ''}]
};
}
addInput = () => {
const existingFormFields = this.state.formFields.map(fields => ({...fields}))
const allFormFieldsAfterAddingNew = [...existingFormFields, {value: ''}]
this.setState({formFields: allFormFieldsAfterAddingNew})
}
onTextChange = (text, index) => {
const existingFormFields = this.state.formFields.map(fields => ({...fields}))
let targetField = {...existingFormFields[index]}
targetField.value = text
existingFormFields[index] = targetField
this.setState({formFields: existingFormFields})
}
render() {
return (
<View style={{flex:1, marginTop:30}}>
{
this.state.formFields.map((field, index) => {
return(
<View key={index}>
<TextInput
name="indent"
style={{height: 40,backgroundColor: 'azure', fontSize: 20}}
placeholder="Type here to translate!"
value={field.value}
onChangeText={(text)=> this.onTextChange(text, index)}
/>
</View>
)
})
}
<TouchableOpacity
style={{ height:30, width:70, backgroundColor:'blue'}}
onPress={this.addInput}>
<Text>Add Form</Text>
</TouchableOpacity>
</View>
)
}
}
export default App
我试图尽可能多地使用一些有用的/上下文相关的名称,以使您了解正在发生的事情。但是,让我们在这里介绍一下核心概念:
使addInput
功能为箭头功能,因为它位于类组件中,所以箭头功能会自动绑定,绑定可能会造成混淆。
您在小吃中this.setState({indent})
做过this.setState({indent: indent})
。请了解,这会在名为indent
的状态下创建另一个state(如果之前未定义)变量,并且与indents
并排保持着从中调用的TextInput的当前缩进值。总之,它保留了最后键入的TextInputs的缩进量。
addInput
基本上是将对象推入状态中的表单字段列表。在创建状态对象之前,我们正在创建一个复制/深克隆状态对象。不建议您使用之前的声明this.state.indents[index] = indent
。 切勿在没有setState
的情况下改变状态。通过this.state.formFields.map(fields => ({...fields}))
,我们首先创建了formFields
数组的副本/克隆,然后返回我们所做的{...fields}
的每个项目,现在我们正在上下文中创建对象的副本/克隆并返回它。这样,我们确保在处理数据时状态不会意外更改。最后,我们只添加一个带有空白value
的新条目,并使用setState
更新状态,然后看到一个新的字段!
对于更新每个数据,我们所做的与您最初在snack
中所做的相同。查找索引并更新值。请注意,数据流与上一点相似。我们使用formFields
的deepClone,从克隆中获取目标,更新目标,然后在获取的克隆中替换新值对象并将其设置为新状态。与第3点非常相似。
作为建议,请先结帐并获得有关JS和React的ES6功能的更多见解。
如果您不知道数据中有多少级,则深克隆可能会很棘手。 Lodash为此具有非常有用的功能:https://lodash.com/docs/4.17.15#cloneDeep
您可以在博览会小吃上测试代码。如果您不确定什么,请在评论中让我知道。
希望它对您有所帮助。干杯!