react-native-blur
react-native-blur copied to clipboard
Android invalid viewRef and circular structure
currently having issues with the rendering on Android
for one, I get
index.android.bundle:9099 Warning: Failed prop type: Invalid prop viewRef
of type object
supplied to BlurView
, expected number
.
in BlurView
then i get into a circular structure error, from what I can tell, my blurview is outside of the target.
Works fine on ios though
<View style={styles.app.container}> <View ref={ (ref) => { if (ref) this.screen = ref; this.setState({referenceReady: true}); } } style={styles.app.container}> {content} </View> {this.screen ? <BlurView viewRef={this.screen} style={{position: 'absolute', top:0, left: 0, bottom: 0, right: 0}} blurType="dark" blurAmount={10}/> : null} </View>
Same problem here. Code is very similar:
<View>
<ScrollView>
<View ref={ ref => { this._scrollViewRef = ref; }}>
{ other views, etc }
</View>
</ScrollView>
{ this.state.shouldShowModal && this._scrollViewRef && (
<BlurView
style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
blurType="light"
blurAmount={ 10 }
viewRef={ this._scrollViewRef }
/>
) }
Error 1 (warning):
Warning: Failed prop type: Invalid prop 'viewRef' of type 'object' supplied to 'BlurView', expected 'number'
This is odd, since in my understanding a ref is always supposed to be an object and when I log it out it is, even on Android.
Error 2 (fatal):
10-30 11:47:46.353 5378-5421/my.app.name E/ReactNativeJS: JSON.stringify cannot serialize cyclic structures
10-30 11:47:46.355 5378-5421/my.app.name I/ReactNativeJS: 'Failed to print error: ', 'C++ exception in \'nativeFlushQueueImmediate\'\n\nDid not get valid calls back from JS...
10-30 11:47:46.355 5378-5421/my.app.name E/ReactNativeJNI: Got JS Exception: Exception calling object as function: JSON.stringify cannot serialize cyclic structures.
Note that in mine the BlurView is neither a child nor a parent of the blurred element.
I have the same issueC++ exception in 'nativeFlushQueueImmediate'\n\nDid not get valid calls back from JS
I was able to make this work on Android by doing the following (all good on iOS):
Drawer (more or less the same happens in my Stack Navigator):
constructor(props) {
super(props);
this.state = {
viewRef: 0
};
}
...
componentDidMount(){
setViewRef = setTimeout(function(){
this.setState({ viewRef: global.HomeView });
}.bind(this), 2000);
}
...
componentWillUnmount(){
clearTimeout(this.setViewRef);
}
...
render() {
return (
<ScrollView>
<BlurView style={styles.absolute} viewRef={this.state.viewRef} blurType="dark" blurAmount={10} />
<SafeAreaView>
...
</SafeAreaView>
</ScrollView>
)
}
```
**Home** screen (the ref I need):
import ReactNative, { findNodeHandle, ... } from 'react-native'; ... componentDidMount() { global.HomeView = ReactNative.findNodeHandle(this.HomeView); } ... render() { return ( <View ref={component => this.HomeView = component}> ... </View> ) }
I am using `global` because I need the _Home_ view reference in the _Drawer_ and _Stack_ Navigators which are rendered before. The reason I'm also using `setTimeout()` - Honestly I don't know another way to do it and haven't tried it with _Redux_ (which might be a possibility) - Let me know of a better way.
One weird thing is that I wasn't able to get a value out of `ReactNative.findNodeHandle` while trying to use `this.refs.HomeView` or even `this.state.HomeView` instead (in the Home screen).
Also note that the _ref_ number will be different for any code change you do and even appears to be completely random at times, so no point in hard-coding it.
Overall I find the experience on Android very poor comparing to iOS, as it clearly takes a snapshot of what's in the background.
I hope this helps!
I was able to make this work on Android by doing the following (all good on iOS):
Drawer (more or less the same happens in my Stack Navigator):
constructor(props) { super(props); this.state = { viewRef: 0 }; } ... componentDidMount(){ setViewRef = setTimeout(function(){ this.setState({ viewRef: global.HomeView }); }.bind(this), 2000); } ... componentWillUnmount(){ clearTimeout(this.setViewRef); } ... render() { return ( <ScrollView> <BlurView style={styles.absolute} viewRef={this.state.viewRef} blurType="dark" blurAmount={10} /> <SafeAreaView> ... </SafeAreaView> </ScrollView> ) }
Home screen (the ref I need):
import ReactNative, { findNodeHandle, ... } from 'react-native'; ... componentDidMount() { global.HomeView = ReactNative.findNodeHandle(this.HomeView); } ... render() { return ( <View ref={component => this.HomeView = component}> ... </View> ) }
I am using
global
because I need the Home view reference in the Drawer and Stack Navigators which are rendered before. The reason I'm also usingsetTimeout()
- Honestly I don't know another way to do it and haven't tried it with Redux (which might be a possibility) - Let me know of a better way.One weird thing is that I wasn't able to get a value out of
ReactNative.findNodeHandle
while trying to usethis.refs.HomeView
or eventhis.state.HomeView
instead (in the Home screen).Also note that the ref number will be different for any code change you do and even appears to be completely random at times, so no point in hard-coding it.
Overall I find the experience on Android very poor comparing to iOS, as it clearly takes a snapshot of what's in the background.
I hope this helps!
what is global.HomeView ?