Как отфильтровать содержимое компонента с помощью строки, пропущенной через реквизит? - PullRequest
0 голосов
/ 23 июня 2019

С текстовым полем в родительском компоненте я хочу фильтровать через несколько дочерних компонентов, где строка передается через реквизиты.Дочерние компоненты были выведены через функцию карты, которая также импортирует данные из API в подпорки.У меня есть вход в консоль пользовательского ввода после передачи в качестве подпорки для ребенка (searchTerm).Моя проблема в том, что я не могу скрыть отображение отдельных компонентов на основе ввода пользователя.Беда у меня в том, что когда кто-то решает спрятаться, он все это делает.Я пробовал indexOf и нашел, что include () более полезен.Я беспокоюсь о своем подходе к проблеме и был бы признателен за мудрость более опытных разработчиков.

// родительский компонент

render() { 

    return ( 
    <React.Fragment>

        <input type="text" className = {styles.searchField} id="searchField" placeholder = "Search..." onChange = {this.getUserInput}/>

            <div className={styles.container}>
                {this.state.importedBooks.map((element, index) => (
                    <Tile key ={index} searchTerm ={this.state.searchTerm} buy ={element.amazon_product_url} 
                    img ={element.book_image} summary ={element.description} url={element.book_image} 
                    book_author ={element.author} book_title ={element.title} />
                ))}      
            </div> 

    </React.Fragment>);
}

}

// дочерний компонент

класс Плитка расширяет React.Component {

public state:{display:boolean} = {display:true};

public getContainerContent = () => {

    const containers: NodeListOf<Element> | null = document.querySelectorAll("#container");

    containers.forEach(element => {
    if (element.innerHTML.toLocaleLowerCase().includes(this.props.searchTerm) !== false) {
        this.setState({display:true});
    }
    else if (this.props.searchTerm == "") {
        this.setState({display:true});
    }
    else {
        this.setState({ display: false });
    }
})

};

public componentWillReceiveProps = () => {
    this.getContainerContent();
}

render() { 
    const renderContainer = this.state.display ? styles.container : styles.hideDisplay; 

    return ( 
    <div className={styles.container} id="container">
        <h1>{this.props.book_title}</h1>
        <h2>{this.props.book_author}</h2>
        <a href={this.props.buy} target="_blank"><img src = {this.props.img} alt="book cover"/></a>
        <p>{this.props.summary}</p>
        <a href={this.props.buy} target="_blank">Purchase</a>
    </div> );
}

}

1 Ответ

0 голосов
/ 24 июня 2019

Я думаю, что проблема связана с методом getContainerContent в вашем дочернем компоненте.
Почему один дочерний компонент должен интересоваться данными, которые принадлежат другим дочерним компонентам?

Способ, которым вы можете решить эту проблему, - это сначала объявить в родительском компоненте, с какими параметрами вы собираетесь сопоставить фильтр при отображении дочерних компонентов.
Затем вы можете перебрать эти объявленные реквизиты и решить, должен ли компонент отображать дочерний компонент или нет .

// parent comp
private shouldDisplayElement (element, searchTerm: string): boolean {
    const propsToMatchFiltersAgainst = ['book_title', 'book_author', 'buy', /* etc... */];

    let shouldDisplay = false;

    for (const p of propsToMatchFiltersAgainst) {
        if (`${element[p]}`.toLowerCase().includes(searchTerm.trim())) {
            shouldDisplay = true;
        }
    }

    return shouldDisplay;
}
// parent's render fn
<div className={styles.container}>
    {this.state.importedBooks.map((element, index) => (
        this.shouldDisplayElement(element, this.state.searchTerm)
            ? <Tile 
                key={index} 
                buy={element.amazon_product_url}
                img={element.book_image} 
                summary={element.description} 
                url={element.book_image}
                book_author={element.author} book_title={element.title} 
            />
            : null
    ))}
</div> 

Таким образом, учитывая текущую ситуацию, вам больше не нужно использовать метод getContainerContent в дочернем компоненте.

...