Marek Czyż
Marek Czyż

Reputation: 199

Uncaught TypeError: Cannot read property 'filterText' of undefined

I passed filterText=this.state.filterText to the Child Table to filter only the films which contain the letters which I've typed into searcher.

Inside Table component I've created function CheckIfFiltered to filter the films and to check if the table contains the "filterText".

The problem is that when I try to run it there is an Error:

"Uncaught TypeError: Cannot read property 'filterText' of undefined"

Although I've passed filterText to a props, to the Table component. Please help me solve this problem.

var Row = React.createClass({
    render: function(){
        return(
            <tr>
                <td>{this.props.episode.title}</td>
                <td><a href ="top">Link</a></td>
            </tr>
        );
    }
});


var Table = React.createClass({
    render: function(){
        var CheckIfFiltered=function (episode, index, ar){			
            if (episode.title.toLowerCase().indexOf(this.props.filterText.toLowerCase()) > -1){
                return true;
            }
            else {
                return false;
            }
        }

        var filter_rows = this.props.episodes.filter(CheckIfFiltered).map(function(episode){
            return <Row episode={episode} key={episode.title} /> ;
        });

        return(
            <div className="row spacer">
                <div className="col-lg-4 col-lg-offset-4">
                    <table width="100%">
                        <tbody>{filter_rows}</tbody>
                    </table>
                </div>
            </div>
        );
    }
});


var Search = React.createClass({

    changeFilteringSearch: function(){
        this.props.changeFiltering(
            this.refs.filterTextInput.value
        );
    },

    render: function(){
        return (
            <div className="row ">
                <div className="col-lg-4 col-lg-offset-4">
                    <input type="search" className="form-control" value = {this.props.filterText} ref="filterTextInput" onChange={this.changeFilteringSearch} className="form-control" placeholder="Search for episode" />
                </div>
            </div>
        );
    }
});


var FilterableEpisodesTable = React.createClass({

    getInitialState: function() {
        return {
            filterText: 'qwerty'
        };
    },

    changeFiltering: function(text){
        this.setState({
            filterText: text
        });
    },

    render: function(){
        return(
            episodes=this.props.episodes,
            <div>
                <Search filterText={this.state.filterText} changeFiltering={this.changeFiltering}/>
                <hr/>
                <Table episodes={episodes} filterText={this.state.filterText}/>
            </div>
        );
    }
});


var episodes = [{title : "Angular with Yeoman",},
                {title : "Using D3 with Rickshaw and Angular",},
                {title : "Canvas with paper.js",},
                {title : "Express.js middleware",},
                {title : "Metro",}
                ];

ReactDOM.render(
    <FilterableEpisodesTable episodes = {episodes}/>,
    document.getElementById('example')
);

Upvotes: 0

Views: 766

Answers (2)

Matt Styles
Matt Styles

Reputation: 2452

CheckIfFiltered runs in a different context as you’ve passed it to filter, so it just needs to be bound.

Either

var CheckIfFiltered=function( episode ){            
  if (episode.title.toLowerCase().indexOf(this.props.filterText.toLowerCase()) > -1){
    return true;
  } else {
    return false;
  }
}.bind( this )

or

var filter_rows = this.props.episodes.filter(CheckIfFiltered.bind( this )).map( ... )

should help you scope it correctly. Alternatively add it as a class method, I think React.createClass autobinds functions but note that if you change to ES2015 syntax the JS native behaviour of never autobinding will take place so you'll have to bind it yourself.

React.createClass({
  CheckIfFiltered: function( episode, index, ar ){          
    return episode.title.toLowerCase().indexOf(this.props.filterText.toLowerCase()) > -1 ? true : false
  },
  render: function() { ... }
})

Upvotes: 1

Fran&#231;ois Richard
Fran&#231;ois Richard

Reputation: 7045

I think this is a simple scope problem, check this and let me know if it helps.

render: function(){
        var self = this;
        var CheckIfFiltered=function (episode, index, ar){          
                if (episode.title.toLowerCase().indexOf(self.props.filterText.toLowerCase()) > -1){
                    return true;
                }
                else{
                    return false;
                }

Upvotes: 0

Related Questions