Javascript 使用setState方法添加子对象

Javascript 使用setState方法添加子对象,javascript,react-native,expo,Javascript,React Native,Expo,我正在尝试使用expo应用程序中的方法this.setState向现有对象添加新的子对象。单击按钮后将添加子对象,该按钮将更新构成子对象的字段 这是我的代码: import React, { Component } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, ImageBackground } from 'react-native'; import CenteredButton from '../compon

我正在尝试使用
expo
应用程序中的方法
this.setState
向现有对象添加新的子对象。单击按钮后将添加子对象,该按钮将更新构成子对象的字段

这是我的代码:

import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ImageBackground } from 'react-native';

import CenteredButton from '../components/CenteredButton';
import { Actions } from 'react-native-router-flux';

var t = require('tcomb-form-native');
var _ = require('lodash');

const Form = t.form.Form;
const stylesheet = _.cloneDeep(t.form.Form.stylesheet);

stylesheet.textbox.normal.borderColor = '#b3b3b5';
stylesheet.textbox.normal.fontFamily = 'RobotoThin';
stylesheet.textbox.normal.backgroundColor = '#fdfdfd';
stylesheet.textbox.normal.fontSize = 18;
stylesheet.textbox.normal.borderWidth = 0.6;
stylesheet.textbox.normal.borderRadius = 10;

stylesheet.textbox.error.fontFamily = 'RobotoThin';
stylesheet.textbox.error.backgroundColor = '#fdfdfd';
stylesheet.textbox.error.fontSize = 18;
stylesheet.textbox.error.borderWidth = 0.6;
stylesheet.textbox.error.borderRadius = 10;

const Email = t.refinement(t.String, email => {
  const regex = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/; 
  return regex.test(email);
});

const EmailTo = t.struct({
  emailPerson: Email,
  emailInsurance:  t.maybe(Email)
});

const options = {
  auto: 'none',
  stylesheet: stylesheet,
  fields: {
    emailPerson: {
      placeholder: 'Email personale',
      autoCapitalize: 'none',
      autoCorrect: false,
    },
    emailInsurance: {
      placeholder: 'Email Assicurazione',
      autoCapitalize: 'none',
      password: true,
    }
  }
}

export default class NessunProblema extends Component {

  constructor(props) {
    super(props);
    this.state = {
      emails: {
        emailPerson: '',
        emailInsurance: ''
      },
      ascertainment: { }
    }
  }

  componentDidMount() {
    this.setState({ ascertainment: this.props.ascertainment });
  }

  _onChange = (emails) => {
    this.setState({ emails });
  }

  _handle = () => {
    const value = this.refs.form.getValue();
    if ( value ) {
      this.setState(prev => ({
        ascertainment: {
          ...prev.ascertainment,
          emails: {
            ...prev.ascertainment.emails,
            emailPerson: value.emailPerson,
            emailInsurance: value.emailInsurance
          }
        }
      }));
    }

    console.log(this.state.emails);
    console.log(this.state.ascertainment);
  }

  render() {
    return (
      <View style={{flex: 1, backgroundColor: 'white' }}>
        <ImageBackground source={require('../images/NoProblem.png')} style={styles.backgroundImage}>
          <View style={{ flex: 2, alignItems: 'center', justifyContent: 'center', width: '100%', paddingHorizontal: 20, top: 10}}>
            <Text style={styles.domanda}>
              Text
            </Text>
            <Text style={styles.domanda2}>
              Text
            </Text>
          </View>

          <View style={{padding: 20}}>
            <Form 
              ref='form'
              options={options}
              type={EmailTo}
              value={this.state.emails}
              onChange={this._onChange}
            />
          </View>

          <CenteredButton
            next={ this._handle }
          />
        </ImageBackground>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  domanda: {
    color: '#00b0ff',
    textAlign: 'center',
    fontSize: 44,
    fontFamily: 'RobotoRegular',
    alignItems: 'center',
    justifyContent: 'center',
    padding: 20
  },
  domanda2: {
    color: 'black',
    textAlign: 'center',
    fontSize: 22,
    fontFamily: 'RobotoRegular',
    alignItems: 'center',
    justifyContent: 'center',
    padding: 20
  },
  testoRosso: {
    color: '#f32a19',
    fontFamily: 'RobotoRegular',
  },
  backgroundImage: {
    flex: 1,
    resizeMode: 'cover'
  },
  textInput: {
    width: '100%',
    paddingHorizontal: 15,
    height: 40,
    marginBottom: 20,
    fontSize: 18,
    borderWidth: 0.6,
    borderColor: 'black',
    borderRadius: 10,
    color: 'black',
    fontFamily: 'RobotoThin',
    backgroundColor: 'white'
  },
});
import React,{Component}来自'React';
从“react native”导入{视图、文本、样式表、TouchableOpacity、ImageBackground};
从“../components/CenteredButton”导入CenteredButton;
从“react native router flux”导入{Actions};
var t=require('tcomb-form-native');
var=要求('lodash');
const Form=t.Form.Form;
const stylesheet=\ u0.cloneDeep(t.form.form.stylesheet);
stylesheet.textbox.normal.borderColor='#b3b5';
stylesheet.textbox.normal.fontFamily='RobotoThin';
stylesheet.textbox.normal.backgroundColor='#fdfdfd';
stylesheet.textbox.normal.fontSize=18;
stylesheet.textbox.normal.borderWidth=0.6;
stylesheet.textbox.normal.borderRadius=10;
stylesheet.textbox.error.fontFamily='RobotoThin';
stylesheet.textbox.error.backgroundColor='#fdfdfd';
stylesheet.textbox.error.fontSize=18;
stylesheet.textbox.error.borderWidth=0.6;
stylesheet.textbox.error.borderRadius=10;
const Email=t.definition(t.String,Email=>{
常量正则表达式=/[a-z0-9!#$%&'*+/=?(?:\.[a-z0-9!#$%&'*+/=?([a-z0-9](?:[a-z0-9-][a-z0-9-][a-z0-9-][a-z0 a-9-][a-z0 a-9-][a-z0 a-9]。+[a-z0;
返回正则表达式测试(电子邮件);
});
const EmailTo=t.struct({
emailPerson:Email,
emailInsurance:t.maybe(电子邮件)
});
常量选项={
自动:“无”,
样式表:样式表,
字段:{
电子邮件发送人:{
占位符:“电子邮件个人”,
自动资本化:“无”,
自动更正:错误,
},
电子邮件保险:{
占位符:“电子邮件助理”,
自动资本化:“无”,
密码:true,
}
}
}
导出默认类NessUnproblem扩展组件{
建造师(道具){
超级(道具);
此.state={
电子邮件:{
emailPerson:“”,
电子邮件保险:“”
},
确定:{}
}
}
componentDidMount(){
this.setState({assecution:this.props.assecution});
}
_onChange=(电子邮件)=>{
this.setState({emails});
}
_句柄=()=>{
常量值=this.refs.form.getValue();
如果(值){
this.setState(prev=>({
确定:{
…先前的确定,
电子邮件:{
…上一次确认电子邮件,
emailPerson:value.emailPerson,
emailInsurance:value.emailInsurance
}
}
}));
}
console.log(this.state.emails);
控制台日志(此状态确定);
}
render(){
返回(
正文
正文
)
}
}
const styles=StyleSheet.create({
多曼达:{
颜色:“#00b0ff”,
textAlign:'中心',
尺码:44,
fontFamily:“机器人神经”,
对齐项目:“居中”,
为内容辩护:“中心”,
填充:20
},
领域2:{
颜色:'黑色',
textAlign:'中心',
尺寸:22,
fontFamily:“机器人神经”,
对齐项目:“居中”,
为内容辩护:“中心”,
填充:20
},
Testoroso:{
颜色:“#f32a19”,
fontFamily:“机器人神经”,
},
背景图片:{
弹性:1,
resizeMode:“封面”
},
文本输入:{
宽度:“100%”,
水平方向:15,
身高:40,
marginBottom:20,
尺码:18,
边框宽度:0.6,
边框颜色:“黑色”,
边界半径:10,
颜色:'黑色',
fontFamily:“RobotoThin”,
背景颜色:“白色”
},
});
我注意到,如果我点击两次按钮,就会得到正确的结果。但是,为什么


我遵循这一点,但没有解决问题。

问题是setState()不同步,值是异步更新的

setState()不会立即改变this.state,但会创建挂起的状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState调用的同步操作,并且可能会对调用进行批处理以提高性能

console.log(this.state.emails)
运行时,它会连续打印正确的文件。我怎样才能解决这个问题?
_handle = () => {
    const value = this.refs.form.getValue();
    if ( value ) {
      this.setState(prev => ({
        ascertainment: {
          ...prev.ascertainment,
          emails: {
            ...prev.ascertainment.emails,
            emailPerson: value.emailPerson,
            emailInsurance: value.emailInsurance
          }
        }
      }));
    }

    console.log(this.state.emails); // will be the emails in the previous state, since setState has not been called yet by react 
    console.log(this.state.ascertainment); // if you click twice, you are still getting the `last` state, but since it is the same as the state you are setting the second time, you get the wrong idea that it is being set if you click twice!
  }