javascriptreactjsreact-reduxunmount

How do I unload components?


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>
    );
}

}


Solution

  • 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().

    1. You are not actually rendering any updates inside the render method. keep in mind that anything inside the 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"/>