问题
UPDATED
DESCRIPTION
I have a listener on a Realm Object for getting updates. When there is an update on the server (or in the client) the function provided to the listener calls setState({}).
The strange part is that even if the console says that everything is ok, and it shows that the render method was called with correct data, I can't see any updates to my app.
If I tap on the screen randomly (after 1s,2s, 20s...) the UI magically updates and everything is correct.
If I do the same setState with a function called from a button it works, I guess because the animation of the button triggers the UI update.
Thanks for reading this.
STEP TO REPRODUCE
You have to update the server_url and credential in order to work.
react-native init test npm install realm react-native link realm
Since realm is not ready for 64-bit you must also be sure t compile only in 32bit in order to avoid app crashing when launched
use this code:
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"
}
}
Some other strange things :
- If I remote debug js to react native debugger (on Windows, but I guess is the same) the problem disappears.
- The same thing happens on 3 different devices( 2 real, 1 emulator)
回答1:
UPDATE 2
setState({}) doesn't work when is inside the listener callback. I've just done a test changing the code in componentDidMount of Home.js, and in this way, it works.
It doesnt work because you are not binding the method that is calling it. it is beyond component context so setState is not there.
Do
openRealmAndLogin = (realm_user) => {...}
instead of regular function as this one will bind the function to context. e.g. you can also bind it in constructor (but from what i've seen you are already doing something similar for other function - so better to keep it consistent)
回答2:
I would suggest that you change the key of the element; this will force it to reload whatever happens.
Ex:
{
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}
/>
)
})
}
来源:https://stackoverflow.com/questions/56044770/ui-doesnt-update-until-tap-on-the-screen-when-setstate-is-called-inside-a-realm