smy
smy

Reputation: 21

React function is not being called back in render()

I am creating a movie searching app with React, Redux and Firebase. I created a function(isPresentMovie) to verify whether the movie has been in Fb or not, and my expectation is that either "Add Movie"/"Remove Movie" button is being returned depending on the result of verification.

import React, { Component } from 'react'
import { connect } from 'react-redux';
import {  addFav, removeFav, getDetail } from '../../store/actions/getDetailAction'
import { firestoreConnect } from 'react-redux-firebase';
import { compose } from 'redux'


const button = {
    marginLeft:'10px',
    marginRight:'10px',
}

export class Favorite extends Component {

        handleRemove = (e) => {
            e.preventDefault();
            this.props.removeFav()
        };

        handleAdd = (e) => {
            e.preventDefault();
            this.props.addFav()
        }

    isPresentMovie = () => {
        const validation = this.props.favorites.filter(favorite => favorite.authorId == this.props.auth.uid).find(favorite => favorite.imdbID == this.props.movie.imdbID); 

        if(validation == undefined){
            return (<button type="submit" className="btn btn-danger btn-bg mt-1" onClick={this.handleRemove} style={button}>Remove From Favorite</button>);
        } else {
            return (<button type="submit" className="btn btn-primary btn-bg mt-1" onClick={this.handleAdd} style={button}>Add To Favorite</button>);
        }
    }

    render() {
        return (
            <div className="d-flex">
               {this.isPresentMovie()}  
            </div>
        )
    }
}

const mapStateToProps = state => ({
    favorites: state.firestore.ordered.favorites,
    auth: state.firebase.auth,
    movie: state.movie.movie,
})

export default compose(
    connect(mapStateToProps,{ addFav, removeFav, getDetail }),
    firestoreConnect([
        { collection: 'favorites' }
    ])
)(Favorite);

Issue 1: Although I use arrow function, the function is not being called in render().The error saying "TypeError: Cannot read property 'filter' of undefined" Tried with .bind(this), the result was same.

Issue 2: I initially suspected that it was not properly rendered out, but if I did not use any methods inside the function, it displayed correctly.

If it is because of the methods, is there any alternative way to verify data in Fb against API data? Or with another way, I can validate data based on the function I created?

Upvotes: 0

Views: 48

Answers (2)

kyle
kyle

Reputation: 2638

The favorites prop isn't defined, probably because the data is in the processing of coming from firebase on the initial load. Another problem you will have is that your buttons need to have the key prop. While favorites is undefined, you can just render null from isPresent, try this:

isPresentMovie = () => {
  if (!Array.isArray(this.props.favorites)) {
    return null;
  }

  const validation = this.props.favorites.filter(favorite => favorite.authorId == this.props.auth.uid).find(favorite => favorite.imdbID == this.props.movie.imdbID); 

  if(validation == undefined){
    return (<button key="no-validation" type="submit" className="btn btn-danger btn-bg mt-1" onClick={this.handleRemove} style={button}>Remove From Favorite</button>);
  } else {
    return (<button key="validation" type="submit" className="btn btn-primary btn-bg mt-1" onClick={this.handleAdd} style={button}>Add To Favorite</button>);
  }
}

Upvotes: 1

royranger
royranger

Reputation: 374

Issue 1: Although I use arrow function, the function is not being called in render().The error saying "TypeError: Cannot read property 'filter' of undefined" Tried with .bind(this), the result was same.

The fact that it is showing this error means that it is indeed calling your isPresentMovie function. But the issue is that this.props.favorites is undefined.

Try a check before calling filter on it, ie

const validation = this.props.favorites && this.props.favorites.filter(favorite => favorite.authorId == this.props.auth.uid).find(favorite => favorite.imdbID == this.props.movie.imdbID); 

Upvotes: 0

Related Questions