2017-06-16 1 views
0

Ich versuche, eine Container-Komponente zu erstellen, die Filterdaten enthält und sie an eine Komponente weitergibt, die die gefilterte Liste darstellt. Diese Container-Komponente erhält ihre Daten von einer übergeordneten Komponente. Der Filter funktioniert einwandfrei und übergibt die gefilterte Liste ordnungsgemäß. Ich schalte eine Klasse auf den Filter-Tags onclick, um die CSS zu ändern. Mein Problem ist, wenn meine Container-Komponente 1 Datensatz gerendert hat und zu einem anderen Datensatz mit ähnlichen Filternamen wechselt, wird die Klasse, die ich für aktive Filter verwende, nicht zurückgesetzt, da React Filter, die sich nicht ändern, nicht neu rendert . Zum Beispiel hat Datensatz 1 die Filter: hasNumbers, hasLetters und Datensatz 2 hat die Filter: hasNumbers, hasSpecialChars. Wenn ich hasNumbers in Dataset 1 umschalte und dann zu Dataset 2 umschalte, behält hasNumbers seine aktive Klasse, da React das nicht rendert (denke ich). Dies ist nur ein Problem mit der Klasse, der Zustand wird ordnungsgemäß aktualisiert.Wie setze ich Klassennamen auf allen JSX-Elementen in einer Komponente auf Requisiten zurück?

Dies ist mein Container-Komponente:

class containerComponent extends React.Component { 
 
    constructor() { 
 
    super() 
 

 
    this.state = ({ 
 
     activeFilters: [] 
 
    }) 
 
    
 
    this.toggleItem = this.toggleItem.bind(this) 
 
    } 
 
    
 
    toggleItem(event) { 
 
    event.target.classList.toggle('active'); 
 

 
    const targetItem = event.target.innerHTML; 
 
    let _activeFilters = [...this.state.activeFilters]; 
 

 
    _activeFilters.indexOf(targetItem) === -1 ? 
 
     _activeFilters = [..._activeFilters, targetItem] : _activeFilters = _activeFilters.filter(activeItem => activeItem != targetItem); 
 

 
    this.setState({ 
 
     activeFilters: _activeFilters 
 
    }) 
 
    } 
 
    
 
    render() { 
 
    return(
 
     <FilterTags items={this.getItems()} toggleItem={this.toggleItem} /> 
 
    ) 
 
    } 
 
} 
 

 
export default containerComponent

Und das ist meine Komponente, die die Liste der Filtertags

const FilterTags = ({items, toggleItem}) => { 
 

 
    return (
 
    <ul className="filterList"> 
 
     <li>Filter: </li> 
 
     {items.map((item, i) => 
 
     <li 
 
      key={i} 
 
      className={`itemFilter-${item.replace(/\s+/g, '-').toLowerCase()}`} 
 
      onClick={toggleItem}>{item}</li> 
 
    )} 
 
    </ul> 
 
) 
 
} 
 

 
export default FilterTags

Sorry, wenn dies eine macht, ist mish mash von es5 und es6, es ist schon eine Weile her und ich ein m versuchen zu lernen React und nicht-jQuery zur gleichen Zeit

Antwort

-1

Reagieren Verwendung key, um verschiedene Elemente einer Liste zu verfolgen. In Ihrem Fall wird das Element nicht neu erstellt, da Sie immer denselben key verwenden, der nur der Index ist. Wenn Sie jedes Mal, wenn FilterTags gerendert werden, unterschiedliche Schlüssel verwenden können, erstellt React Ihre <li> Elemente neu und entfernt zuvor erstellte Elemente. Als Workaround können Sie die aktuelle Uhrzeit mit dem Index verketten und als key verwenden.

const FilterTags = ({items, toggleItem}) => { 
    const time = Date.now(); 
    return (
    <ul className="filterList"> 
     <li>Filter: </li> 
     {items.map((item, i) => 
     <li 
      key={time + "-" + i} 
      className={`itemFilter-${item.replace(/\s+/g, '-').toLowerCase()}`} 
      onClick={toggleItem}>{item}</li> 
    )} 
    </ul> 
) 
} 

export default FilterTags 

Allerdings empfehle ich nicht die Vorgehensweise, die Sie hier verwenden. In React ist es keine gute Idee, das DOM explizit wie bei event.target.classList.toggle('active') zu mutieren. Stattdessen sollten Sie in der Rendermethode auf das für Sie reagieren lassen. Dann sind Sie immer sicher und werden diese Art von Problemen auf der ganzen Linie nicht begegnen. Aber Sie müssen activeFilters als Prop zu Ihrer FilterTags-Komponente übergeben.

class ContainerComponent extends React.Component { 
    constructor() { 
    super() 

    this.state = ({ 
     activeFilters: [] 
    }) 

    this.toggleItem = this.toggleItem.bind(this) 
    } 

    toggleItem(event) { 

    const targetItem = event.target.textContent; 
    let _activeFilters = [...this.state.activeFilters]; 

    _activeFilters.indexOf(targetItem) === -1 ? 
     _activeFilters = [..._activeFilters, targetItem] : _activeFilters = _activeFilters.filter(activeItem => activeItem != targetItem); 

    this.setState({ 
     activeFilters: _activeFilters 
    }) 
    } 

    render() { 
    return(
     <FilterTags items={this.getItems()} toggleItem={this.toggleItem} activeFilters={this.state.activeFilters}/> 
    ) 
    } 
} 

export default containerComponent 

und es dann bedingt active Klasse in der Render-Methode von filter verwenden, um hinzuzufügen.

const FilterTags = ({items, toggleItem, activeFilters}) => { 

    return (
    <ul className="filterList"> 
     <li>Filter: </li> 
     {items.map((item, i) => 
     <li 
      key={i} 
      className={`itemFilter-${item.replace(/\s+/g, '-').toLowerCase()}` + (activeFilters.indexOf(item) !== -1 ' active' : '')} 
      onClick={toggleItem}>{item}</li> 
    )} 
    </ul> 
) 
} 

export default FilterTags 
+0

Danke für die Hilfe. Aus irgendeinem Grund ist mir nicht in den Sinn gekommen, dass die Verwendung von classList das dom dom und nicht das space dom beeinflusst. Ich musste nur das '?' in der zweiten Renderfunktion –

Verwandte Themen