2 Пользовательский интерфейс не обновляется до тех пор, пока нажатие на экран не будет вызвано вызовом setState внутри обратного вызова слушателя области

вопрос создан в Wed, May 8, 2019 12:00 AM

ОБНОВЛЕНО

ОПИСАНИЕ

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

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

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

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

Спасибо, что прочитали это.

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

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

реактивный исходный тест init НПМ установить царство Реакционно-нативная область ссылок

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

используйте этот код:

App.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
  1. Он не использует Expo
    2019-05-11 10: 35: 42Z
  2. Тогда, возможно, вы можете предоставить ссылку на github или что-то еще.
    2019-05-11 10: 36: 14Z
  3. Я обновил пример
    2019-05-11 16: 30: 57Z
2 ответа                              2                         

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

Пример:

{
  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}
      />
    )
  })
}
    
1
2019-05-11 14: 47: 38Z
  1. Я пытался, это то же самое.
    2019-05-11 15: 18: 13Z
  2. @ DxW вы можете добавить обратный вызов для setState и убедиться, что он срабатывает при добавлении статьи? this.setState ({...}, () = > alert (1)) например; также вы должны удалить forceUpdate, так как состояние меняется: -)
    2019-05-11 15: 21: 20Z
  3. Я пробовал, это то же самое. Я также попытался использовать key = {Date (). GetTime ()}, чтобы быть уверенным в принудительном повторном рендеринге в каждом цикле, но ничего. Странно то, что при нажатии на экран все обновляется хорошо. Но в консоли ничего не происходит, и последний цикл рендеринга (с правильными данными) произошел, когда уведомление было получено от слушателя.
    2019-05-11 15: 24: 50Z
  4. да, обратный вызов срабатывает. Поскольку после закрытия оповещения происходит взаимодействие, пользовательский интерфейс обновляется. Но я думаю, только из-за взаимодействия. Я загружаю пример. Если я использую кнопку для изменения состояния, она работает хорошо, «на удивление» даже с TouchableWithoutFeedback (для избежания анимации, которая может вызвать повторную визуализацию).
    2019-05-11 15: 45: 19Z
  5. я обновил пример в своем вопросе
    2019-05-11 15: 56: 35Z
  

ОБНОВЛЕНИЕ 2

     

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

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

Do

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

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

    
1
2019-05-12 09: 19: 41Z
  1. Я попытался, но это не решило проблему :( setState вызывается в обратном вызове слушателя, и я вижу изменение данных и запуск метода render в журнале консоли. Единственная проблема в том, что поток пользовательского интерфейса (возможно?) Не отображает изменения, пока я не нажму
    2019-05-12 14: 30: 35Z
источник размещен Вот