Пользовательский интерфейс не обновляется до тех пор, пока не будет вызвано касание на экране, когда setState вызывается в обратном вызове слушателя области. - PullRequest
9 голосов
/ 08 мая 2019

ОБНОВЛЕНО

ОПИСАНИЕ

У меня есть прослушиватель объекта Realm для получения обновлений.Когда на сервере (или в клиенте) происходит обновление, функция, предоставляемая слушателю, вызывает setState ({}).

Странная часть в том, что даже если консоль говорит, что все в порядке, и онапоказывает, что метод рендеринга был вызван с правильными данными, я не вижу никаких обновлений для моего приложения.

Если я случайно нажимаю на экран (через 1 с, 2 с, 20 с ...), пользовательский интерфейс волшебным образом обновляетсяи все правильно.

Если я сделаю то же самое setState с функцией, вызываемой из кнопки, она работает, я думаю, потому что анимация кнопки вызывает обновление пользовательского интерфейса.

Спасибо за чтение этого.

ШАГ ДЛЯ ВОСПРОИЗВЕДЕНИЯ

Для работы необходимо обновить server_url и учетные данные.

реагировать-нативныйinit test npm install realm response-native link realm

Поскольку область не готова для 64-битной среды, вы также должны быть уверены, что t компилируются только в 32-битной версии, чтобы избежать сбоя приложения при запуске

useэтот код:

приложение.js

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

import Realm from 'realm'

import { SERVER_URL } from "./config/realm";
import { Utente } from "./config/schema";


export default class App extends Component {

  loginAsync = async () => {

    var realm_user = Realm.Sync.User.current

    if(!realm_user){
      const credentials = Realm.Sync.Credentials.usernamePassword('admin', '******' ,false);
      realm_user = await Realm.Sync.User.login(SERVER_URL, credentials);
    }

    const config = realm_user.createConfiguration({
      schema: [
        Utente, 
        Realm.Permissions.Permission,
        Realm.Permissions.User,
        Realm.Permissions.Role],
      schemaVersion: 1,
    });

    this.realm = new Realm(config);


    var connectedUserData = this.realm.objects("Utente").filtered("id = $0", realm_user.identity)
    connectedUserData.subscribe()


    connectedUserData.addListener((connectedUserData)=>{

      if(connectedUserData[0]){
        this.setState({
          connectedUserData: connectedUserData[0]
        })
      }

    })

  }

  constructor(props){
    super(props)

    this.loginAsync()

    this.state = {
      connectedUserData: {
        nome: 'not loaded'
      }
    }

  }



  render() {
    return (
      <View style={styles.container}>
        <Text>{ this.state.connectedUserData.nome }</Text>
      </View>
    );
  }
}



Schema.js

export const Utente = {
    name: "Utente",
    primaryKey: "id",
    properties: {
        id: "string",
        nome: 'string?',
        permissions: '__Permission[]'
    }
}

Package.json

{
  "name": "testBaseRealm",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "react": "16.6.3",
    "react-native": "0.57.7",
    "realm": "^2.27.0-rc.3"
  },
  "devDependencies": {
    "@babel/core": "7.4.4",
    "@babel/runtime": "7.4.4",
    "babel-jest": "24.8.0",
    "jest": "24.8.0",
    "metro-react-native-babel-preset": "0.54.1",
    "react-test-renderer": "16.6.3"
  },
  "jest": {
    "preset": "react-native"
  }
}

Некоторые другие странные вещи:

  • ЕслиЯ удаленно отлаживаю js, чтобы реагировать на собственный отладчик (в Windows, но я думаю, что это то же самое), проблема исчезает.
  • То же самое происходит на 3 разных устройствах (2 реальных, 1 эмулятор)

Ответы [ 2 ]

2 голосов
/ 12 мая 2019

ОБНОВЛЕНИЕ 2

setState ({}) не работает, когда находится внутри обратного вызова слушателя. Я только что сделал тест, изменив код в componentDidMount из Home.js, и таким образом это работает.

Это не работает, потому что вы не привязываете метод, который его вызывает. он находится за пределами контекста компонента, поэтому setState отсутствует.

У

   openRealmAndLogin = (realm_user) => {...}

вместо обычной функции, так как эта свяжет функцию с контекстом. например Вы также можете связать это в конструкторе (но из того, что я видел, вы уже делаете нечто подобное для другой функции - так что лучше сохранять ее согласованность)

1 голос
/ 11 мая 2019

Я бы посоветовал вам изменить ключ элемента;это заставит его перезагружаться, что бы ни случилось.

Пример:

{
  articoli.map(articolo => {
    const isLoved = connectedUserData.loved_articles.filtered("id = $0", articolo.id ).length
    const isLiked = connectedUserData.liked_articles.filtered("id = $0", articolo.id ).length
    const numCommenti = articolo.commenti.length

    return (
      <SchedaArticolo
        key={ `ALL_${articolo.id}_${isLoved}_${isLiked}_${numCommenti}` }
        articolo={articolo}
        isLoved={isLoved}
        isLiked={isLiked}
        numCommenti={numCommenti}
      />
    )
  })
}
...