I have project component that I'm duplicating according to a project list. Once the page is rendered and all Project components are displayed I want to enable a search functionality.
When I perform the search and I filter the project list, the old results are displayed near the new results after search!
How to cause it to display only search results?
Updated code (Working):
class ProjectsList extends Component {
state = {
projectsDetails: [......],
filterKey: null
}
componentWillMount() {
//service.getProjectDetails();
}
handleSearchChange(e) {
this.setState({ filterKey: e.target.value });
}
render() {
const { filterKey, projectsDetails } = this.state;
const filteredProjects = filterKey
? projectsDetails.filter(item =>
item.Name.toLowerCase().includes(filterKey.toLowerCase()) && item.FabricationConfigs !== null
)
: projectsDetails.filter(item =>
item.FabricationConfigs !== null
);
return (
<table width="100%">
<tbody>
<tr>
<td>
<div className="Toolbar2">
<table width="100%">
<tbody>
<tr>
<td>
<h1>Projects</h1>
</td>
<td width="20%" align="right">
<Search labelText="" id="search-1" onChange={ this.handleSearchChange.bind(this) }/>
</td>
</tr>
</tbody>
</table>
<hr></hr>
</div>
<div className="inline">
{filteredProjects.map(item =>
<Project
key={item.Name}
name={item.Name}
description={item.Description}
configurations={item.FabricationConfigs}/>)}
</div>
</td>
</tr>
</tbody>
</table>
);
}
}
There are couple of issues here. 1. You are mutating the state with this line:
this.state.filteredProjects = this.state.filteredProjects.filter
and this line:
projectsComponents.push
Which is not recommended at all when working with react
, i believe this is why you needed a method like this.forceUpdate()
.
render
will run on each update of state or new props. so you can use the filtered value stored in the state
, grab your list, and store a filtered version of it based that value.
Then just render the filtered list with .map
.Here is a simple running example:
class App extends React.Component {
state = {
list: [{ name: "John" }, { name: "Jane" }, { name: "Mike" }],
filterKey: null
};
onFilterChange = ({ target }) => {
this.setState({ filterKey: target.value });
};
render() {
const { filterKey, list } = this.state;
const filteredList = filterKey
? list.filter(item =>
item.name.toLowerCase().includes(filterKey.toLowerCase())
)
: list;
return (
<div>
<input
value={filterKey}
onChange={this.onFilterChange}
placeholder="filter..."
/>
<hr />
{filteredList.map(item => (
<div>{item.name}</div>
))}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"/>