I have a simple react app, which I am using to display a list of users. I have a search box, which filters the list of users and returns the searched user,
However, When I search for users using the search box, I get a TypeError: Cannot read property 'filter' of undefined
The page initially displays fine, it just when I search for the users that the error is thrown. I know the users are being generated correctly because I console logged filteredUsers
The users are all outputted correctly.
Here is my App.js
import { useState } from 'react';
import React from 'react';
import CardList from './ponents/CardList';
import SearchBox from './ponents/SearchBox';
import { users } from './users';
import 'tachyons';
const App = () => {
const [state, setState] = useState({
users,
searchField: '',
});
const filteredUsers = state.users.filter((user) => {
return user.name.toLowerCase().includes(state.searchField.toLowerCase());
});
const onSearchChange = (e) => {
setState({ searchField: e.target.value });
};
return (
<div className='App tc'>
<h1>RoboFriends</h1>
<SearchBox searchChange={onSearchChange} />
<CardList robots={filteredUsers} />
</div>
);
};
export default App;
and here is my SearchBox.js
import React from 'react';
const SearchBox = ({ searchField, searchChange }) => {
return (
<div className='pa2'>
<input
className='pa3 ba b--green bg-lightest-blue'
type='search'
placeholder='Search Users'
onChange={searchChange}
/>
</div>
);
};
export default SearchBox;
I have a simple react app, which I am using to display a list of users. I have a search box, which filters the list of users and returns the searched user,
However, When I search for users using the search box, I get a TypeError: Cannot read property 'filter' of undefined
The page initially displays fine, it just when I search for the users that the error is thrown. I know the users are being generated correctly because I console logged filteredUsers
The users are all outputted correctly.
Here is my App.js
import { useState } from 'react';
import React from 'react';
import CardList from './ponents/CardList';
import SearchBox from './ponents/SearchBox';
import { users } from './users';
import 'tachyons';
const App = () => {
const [state, setState] = useState({
users,
searchField: '',
});
const filteredUsers = state.users.filter((user) => {
return user.name.toLowerCase().includes(state.searchField.toLowerCase());
});
const onSearchChange = (e) => {
setState({ searchField: e.target.value });
};
return (
<div className='App tc'>
<h1>RoboFriends</h1>
<SearchBox searchChange={onSearchChange} />
<CardList robots={filteredUsers} />
</div>
);
};
export default App;
and here is my SearchBox.js
import React from 'react';
const SearchBox = ({ searchField, searchChange }) => {
return (
<div className='pa2'>
<input
className='pa3 ba b--green bg-lightest-blue'
type='search'
placeholder='Search Users'
onChange={searchChange}
/>
</div>
);
};
export default SearchBox;
Share
Improve this question
asked Feb 9, 2021 at 9:49
user6248190user6248190
1,2692 gold badges20 silver badges36 bronze badges
2 Answers
Reset to default 4Because you are using state.users here, filter expect it to be an array.
const filteredUsers = state.users.filter((user) => {
return user.name.toLowerCase().includes(state.searchField.toLowerCase());
});
so you need to set the initial state as an array
const [state, setState] = useState({
users: [], //or a initial value of array of users.
searchField: '',
});
You also need to retain the users when you update the state.
const onSearchChange = (e) => {
setState( prev => ({ ...prev, searchField: e.target.value }));
};
//OR
const onSearchChange = (e) => {
setState({ ...state, searchField: e.target.value });
};
However, this line is not good because it's being called on every render, you should probably "upgrade" it with useMemo like this.
const filteredUsers = useMemo(() => state.users.filter((user) => {
return user.name.toLowerCase().includes(state.searchField.toLowerCase());
}), [state])
Change
const onSearchChange = (e) => {
setState({ searchField: e.target.value });
};
to
const onSearchChange = (e) => {
setState({ searchField: e.target.name.value });
};
And make users into an array