【问题标题】:setState function not assigning boolean.. why?setState 函数没有分配布尔值。为什么?
【发布时间】:2019-05-20 16:23:20
【问题描述】:

我是原生反应的新手,我无法理解这种行为。 在异步函数中,我将加载布尔值设置为 api 调用之前的状态。 现在奇怪的是:收到响应后,我无法将加载布尔值设置回 false。它只是在 setState 函数处等待而没有到达回调。

我已经尝试在多次调用中为每个值设置状态。或全部在一个函数调用中。我还尝试将整个响应分配给状态。 在本机反应中,我可以在从后端获取响应后控制台记录响应。我也可以在离开加载布尔值(到达回调)时将响应分配给状态..但是在尝试将加载布尔值设置回false时不能。 提示(也许): 在 json 响应中,我包含一个数组。当省略数组(不将其分配给状态)时,它的行为就像它应该...... 请帮忙!

// here my mistery
export default class App extends React.Component {  
 constructor(props) {
  super(props);
 this.state = {
  loading: false,   
}
}

async onLogin() {
try {

  this.setState({ loading: true }, function () {
    console.log('loading is:' + this.state.loading)
  }); //works great

  const { name, password } = this.state;

  //here the api call
  const response = 
 await fetch(`http://10.0.2.2:3000/api/login/${name}&${password}`);
  const answer = await response.json();

  if (answer.user == 'OK') {

    //now the strange function-call
    this.setState({
      tickets: answer.tickets, //this is the array..!
      title: answer.event.title,
      token: answer.token.token,
      tokenDa: true,
      //loading: false, //only reaching callback when commenting that out
    }, function () {
      console.log('tickets are :' + this.state.tickets[0].kategorie)
    })

    // same behaviour here 
    // this.setState({loading: false},  function(){
    //   console.log('loading ist ' + this.state.loading);
    // });
  }
}
catch{
  console.log('in CATCH ERROR')
}
}

// here also the render function in case that matters:
render() {
if (this.state.loading) {
  return (
    <View style={styles.container}>
      <ActivityIndicator size='large' />
    </View>
  );
}

return this.state.tokenDa ? (
  <View style={styles.container}>
    <Text>Event Title : {this.state.title} </Text>


    <Button
      title={'scan'}
      style={styles.input} 

    />
    {this.state.tickets.map((ticket, i) => (
      <div key={i}>
        <Text >TicketKategorie : {ticket.kategorie}</Text>
        <Text > Datum und Türöffnung {ticket.gueltig_am}</Text>
        <Text >Verkauft {ticket.verkauft}</Text>
        <Text >Eingescannt {ticket.abbgebucht}</Text>
      </div>
    ))}
  </View>
) : (
    <View style={styles.container}>

      <TextInput
        value={this.state.name}
        onChangeText={(name) => this.setState({ name })}
        placeholder={'Username'}
        style={styles.input}
      />
      <TextInput
        value={this.state.password}
        onChangeText={(password) => this.setState({ password })}
        placeholder={'Password'}
        secureTextEntry={true}
        style={styles.input}
      />

      <Button
        title={'Login'}
        style={styles.input}
        onPress={this.onLogin.bind(this)}
      />
    </View>

  )
};
};

结果是:由于加载属性导致的加载屏幕,我无法将其设置回 false。为什么会这样!?

【问题讨论】:

  • 嗨美索土豆!顺便说一句,好名字。刚刚给你写了一个答案,如果这对你有帮助,请告诉我。
  • 包含映射数组的 div 标签导致了这种行为。 HTML 标签在 react native 中无效。 o_0
  • 呃,这听起来完全是一个不同的错误。

标签: reactjs native


【解决方案1】:

您需要将其余代码包装在第一个 setState 的回调中,如下所示...

this.setState({ loading: true }, async function () {
  const { name, password } = this.state;
  const response = 
 await fetch(`http://10.0.2.2:3000/api/login/${name}&${password}`);
  const answer = response.json();

  if (answer.user == 'OK') {
    this.setState({
      tickets: answer.tickets, //this is the array..!
      title: answer.event.title,
      token: answer.token.token,
      tokenDa: true,
      loading: false
    });
  }
});

【讨论】:

  • 感谢您的解释!事实上我已经尝试过了,但是它抛出了一个 syntaxError 'Can not use keyword 'await' outside an async function' .. 我应该改用 Promise 吗?或者这里有什么问题?
  • 更新了答案,将async添加到setState中的回调函数中。让我知道这是否有帮助。
  • 不幸的是没有......使用这个解决方案它甚至不再分配响应(虽然服务器正在运行并响应,但我尝试了我的旧方法)......我认为我们在这里错过了一些东西
  • 你能不能试试这个promise,让我们看看它是否有效
  • 我发现了这个错误。问题出在
    标签中,这在 react native 中是不允许的。
【解决方案2】:

正如您可能已经推断出的,您的 setState 的异步性质存在问题。为了解决这个问题,我们可以创建另一个函数来处理实际的 API 请求,并在第一个 set-state 的回调中使用它。

setLoading = () => {
    this.setState({ loading: true }, () => this.onLogin())
}

onLogin = async () => {
  const { name, password } = this.state;

  //here the api call
  const response = await fetch(`http://10.0.2.2:3000/api/login/${name}&${password}`);
  const answer = await response.json();

  if (answer.user == 'OK') {
    this.setState({
      tickets: answer.ticketsm
      title: answer.event.title,
      token: answer.token.token,
      tokenDa: true,
      loading: false
    }, function () {
      console.log('tickets are :' + this.state.tickets[0].kategorie)
    })
}

【讨论】:

    猜你喜欢
    • 2020-01-17
    • 1970-01-01
    • 2020-07-07
    • 2023-03-26
    • 2011-01-29
    • 1970-01-01
    • 2020-02-01
    • 2021-04-22
    相关资源
    最近更新 更多