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>
);
}
}
Let's say you are rendering a list:
state = {
list: [{code: 'a'},{code: 'b'},{code: 'c'}],
};
//some render function
<div>{this.state.list.map(item => <Item item={item} />}</div>
In order for one of those Items no unmount you must un-render them.
so you can remove one by index (for example). You can use your function for filtering.
removeByIndex(idx) {
this.setState({
list: this.state.list.filter((item, index) => index !== idx),
});
}
Thus the Item component with said index will be un-rendered and so unmounted.
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"/>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.