0

Hi i am trying to get the data from my database, in componentDidMount(), it works fine with this :

componentDidMount() {
  firebase.database().ref('/users/' + user.uid).once('value').then(function(snapshot) { 
      var valeur = snapshot.val();
      return valeur;
  });
  this.setState({userData:valeur});
}

I just want to know how can i assign this data to a variable that can be use outside of this function, i tried setstate and using variable that i declare outside nothing work i get :react native possible unhandled promise rejection (id 0) Typeerror: this.setState is not a function. Thank you

Andrew
  • 26,706
  • 9
  • 85
  • 101
quentin mayer
  • 137
  • 1
  • 1
  • 12

3 Answers3

1

You have to setState inside the .then function.

Then you can access your value with this.state.userData.

It will be undefined just after mounting then defined when your fetch resolves, so integrate a mechanism that checks for that.

For your undefined problem, a simple solution would be that for instance:

render() {
    return (
      <View>{this.state.userData && this.state.userData.photo}</View>
    )
}

Edit: also like Kai pointed out I am not sure you have access to this instance inside .then callback if you don't use arrow notation.

Quentin C
  • 1,739
  • 14
  • 26
  • Yes i work now but its undefined so what kind of system do you mean ? – quentin mayer Mar 14 '19 at 19:44
  • Can you console.log snapshot .val to be sure it s defined pls? Inside the .then – Quentin C Mar 14 '19 at 19:47
  • yes it work inside the then but not outside i think its cause it execute it before the .then end so is there a way to wait for the .then to finish before keep on going through the code – quentin mayer Mar 14 '19 at 19:56
  • Show all your code pls and put console.log(this.state.userData) in your component – Quentin C Mar 14 '19 at 20:05
  • Thanks, try using componentDidMount instead of WillMount. From React doc: ```Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead.```. Also WillMount is considered deprecated – Quentin C Mar 14 '19 at 20:25
  • It change nothing i think i have to use async and await but i don't know how – quentin mayer Mar 14 '19 at 20:29
  • async/await is just another way to write asynchronous code. .then() is fine for a single fetch like you are doing. – Quentin C Mar 14 '19 at 20:33
  • So why it didn't wait for the call to end ? – quentin mayer Mar 14 '19 at 20:38
  • put your console.log(this.state.userData) just before the return() and not at the end pls. Be careful, the return() not the render() – Quentin C Mar 14 '19 at 20:38
  • Yes i know it work but the when the app is anitialize the setstate is not done so i can't access the state directly – quentin mayer Mar 14 '19 at 20:49
  • Yes that's why you have to put logic before accessing it, for instance you can do: `render(
    {this.state.userData ? this.state.userData : 'We are loading your information...'}
    )`. You can also just do `{this.state.userData && put whatever you want to do with defined userData here}`
    – Quentin C Mar 14 '19 at 20:50
  • Yes state.userData won't be defined until .then() fires. But React will refresh automatically the component when it gets defined, this is the purpose of .setState. – Quentin C Mar 14 '19 at 20:54
  • Its defined as null, when i try to use the data for exemple this.state.userDate.photo i get an error : photo is not defined – quentin mayer Mar 14 '19 at 21:00
  • Yes, try my code just above. By doing `{this.state.userData && 'what you want to do with defined value here'}`. The `&&` checks that userData is not `null` nor `undefined` nor `empty string` before accessing it, so you won't get this error. You have to put it directly into your component. I will edit in my answer – Quentin C Mar 14 '19 at 21:01
  • You're welcome, React is hard to understand at the beginning but then it's a really robust framework, bye! – Quentin C Mar 14 '19 at 21:07
1
class Search extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      films: [],
      isLoading: false,
      userData: null
   }
   this.searchedText = ""
   this.localData=null;
  }



  componentWillMount() {

    user = firebase.auth().currentUser;

      firebase.database().ref('/users/' + user.uid).once('value').then(snapshot => {

      pro = snapshot.val()
      this.setState({userData: pro});

});


    this.setState({ isLoading: true })
    getFilmsFromApiWithSearchedText().then(data => this.setState({ films: data.results }))
      this.setState({ 
       films: data.results,
       isLoading: false
      })


      console.log(this.state.userData)
  }


  _displayLoading() {
    if (this.state.isLoading) {
      return (
        <View style={styles.loading_container}>
          <ActivityIndicator size='large' />
        </View>
      )
    }
  }

  _signOut() {
    firebase.auth().signOut();
  }

  _displayDetailForFilm = (idFilm) => {
    this.props.navigation.navigate("FilmDetail", { idFilm: idFilm })
  }

render() {
    return (
      <View style={styles.main_container}>
        <StatusBar
        hidden = {false}
        backgroundColor="#F1D145"
        ></StatusBar>
        <TouchableOpacity onPress={() => this._signOut()} style={styles.button} activeOpacity={0.8}>
          <Text style={styles.button_text}>Déconnexion</Text>
        </TouchableOpacity>
        <Text>{user.uid}</Text>

        <FlatList
        data={this.state.films}
        keyExtractor={(item) => item.id.toString()}
        renderItem={({item}) => <FilmItem film={item} displayDetailForFilm={this._displayDetailForFilm}/>}
        />
        {this._displayLoading()}
      </View>
    )
}
}


        this.setState({ isLoading: true })
        getFilmsFromApiWithSearchedText().then(data => this.setState({ films: data.results }))
          this.setState({ 
           films: data.results,
           isLoading: false
          })


          console.log(this.state.userData)
      }

Here is all the code i already do console.log(this.state.userData) it return null

quentin mayer
  • 137
  • 1
  • 1
  • 12
0

Switch the anonymous function that you're passing to .then to an arrow function to allow you to use the this from the class scope.

Plenty of information elsewhere on this

Kai
  • 2,529
  • 1
  • 15
  • 24