Kureev / react-native-blur

React Native Blur component
MIT License
3.77k stars 557 forks source link

Android invalid viewRef and circular structure #241

Open bdanis opened 7 years ago

bdanis commented 7 years ago

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} {this.screen ? <BlurView viewRef={this.screen} style={{position: 'absolute', top:0, left: 0, bottom: 0, right: 0}} blurType="dark" blurAmount={10}/> : null}

beneichler commented 6 years ago

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.

hectorsuarezm commented 6 years ago

I have the same issueC++ exception in \'nativeFlushQueueImmediate\'\n\nDid not get valid calls back from JS

gesf commented 6 years ago

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!

pbthakre commented 5 years ago

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!

what is global.HomeView ?