Nick Nick - 1 year ago 128
React JSX Question

Cannot read lowercase react js

Im using react to build a filtered search for my data. It was all working correctly but then I go an error: Uncaught (in promise) TypeError: Cannot read property 'toLowerCase' of undefined.

When I update the state search to null the error become 'toLowerCase' of null. But when I put it as an empty string the error become = 'undefined'.

Just like I said, everything was working fine and this error came suddenly, Please I need your help

Heres the code

var React = require('react');
var firebase = require('firebase');
var $ = require('jquery');
var axios = require('axios');
var notify = require('bootstrap-notify');
var {Link} = require('react-router');

var SuppliersList = React.createClass({

getInitialState: function(event){
return{
search:'Nicolas',
data: [],
}
},
updateSearch : function(event) {
//this.setState({search: event.target.value.substr(0, 20)});
},
componentDidMount: function(){
firebase.database().ref('/suppliers/').once('value').then(function(snapshot) {
var arr = Object.values(snapshot.val());
this.setState({data: arr,activity:false});
}.bind(this));
},

render: function () {
var filteredSuppliers = this.state.data.filter(
(item) => {
return item.name.toLowerCase().indexOf(
this.state.search.toLowerCase()) !== -1;
}
)

var items = filteredSuppliers.map((item, i)=>
<tr key={item.id}>
<td>{item.name}</td>
<td>{item.email}</td>
<td>{item.phone}</td>

<td><Link className="btn btn-primary" to={'/edit/'+item.id}>Edit</Link></td>
<td><Link className="btn btn-danger" to={'/delete/'+item.id}>Delete</Link></td>
<td><a href="#" className="btn btn-warning" role="button" data-title="johnny" data-id="1">Favourite</a></td>
</tr>
);
return (
<div>
<div style={{marginLeft:'50%'}} className="loader"></div>
<input type="text" value={this.state.search} style={{marginTop:20}} placeholder="search a supplier" onChange={this.updateSearch} className="form-control" id="usr"/>

<table className="table table-striped table-hover table-users">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th></th>
<th></th>
</tr>
</thead>

<tbody>
{items}
</tbody>
</table>
</div>

)},
});

var Suppliers = React.createClass({
render: function(){
return (
<div>
<nav className="navbar navbar-default navbar-fixed">
<div className="container-fluid">
<div className="navbar-header">

<button type="button" className="navbar-toggle" data-toggle="collapse" data-target="#navigation-example-2">
<a href="#/branch">
<i className="fa fa-store"></i>
</a>
</button>

<button type="button" className="navbar-toggle" data-toggle="collapse" data-target="#navigation-example-2">
<a href="#/delete">
<i className="fa fa-trash"></i>
</a>
</button>

<button type="button" className="navbar-toggle" data-toggle="collapse" data-target="#navigation-example-2">
<a href="#/edit">
<i className="fa fa-edit"></i>
</a>
</button>

<button type="button" className="navbar-toggle" data-toggle="collapse" data-target="#navigation-example-2">
<a href="#/add">
<i className="fa fa-plus"></i>
</a>
</button>

<a className="navbar-brand" href="#">Suppliers</a>
</div>
<div className="collapse navbar-collapse">
<ul className="nav navbar-nav navbar-left">

</ul>
<ul className="nav navbar-nav navbar-right">
<li>
<a href="#/add">
<i className="fa fa-plus"></i>
</a>
</li>

<li>
<a href="#/delete">
<i className="fa fa-trash"></i>
</a>
</li>

<li>
<a href="#/edit">
<i className="fa fa-edit"></i>
</a>
</li>

<li onClick={this.refresh}>
<a>
<i className="fa fa-refresh"></i>
</a>
</li>

<li>
<a href="#/branch">
<i className="fa fa-map-marker"></i>
</a>
</li>

</ul>
</div>
</div>
</nav>

<table className="table table-hover table-striped">

<SuppliersList/>

</table>
</div>
)},

refresh: function(){
location.reload();
}
});

module.exports = Suppliers;

Answer Source

Problem is with this piece of code

var filteredSuppliers = this.state.data.filter(
  (item) => {
    return item.name.toLowerCase().indexOf(
      this.state.search.toLowerCase()) !== -1;
  }
)

this.state.search is undefined / null, therefore you cannot read properties of it.

I would recommend just returning all items in case search is not defined / null, generally any falsey value, therefore changing that code to:

var filteredSuppliers = this.state.search ? this.state.data.filter(
  (item) => {
    return item.name.toLowerCase().indexOf(
      this.state.search.toLowerCase()) !== -1;
  }
) : this.state.data

If you however get error

'undefined' is not a function (evaluating 'item.name.toLowerCase()')

then you need to call item.name.toString.toLowerCase()..., because you can run toLowerCase only on strings.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download