2016-08-26 7 views
1

Reactで値のリストを使用してフィルタリングしようとしています。値のリストをフィルタリング可能なコンテンツとして渡す

私のすべての「タグ」には、その関連性を示す「タグレベル」があります。

私はそれが同じである(すなわち、同じであればタグを繰り返さない)タグを "キャンセル"したいと思う。

  • 私は第二行は2以上の「taglevel」とすべてtag.nameを表示する1

  • の「taglevel」を持つすべてのtag.nameを表示する最初の行をしたいです。

"タグ"の値を表示したりフィルタリングすることができません。おそらく、私が間違いを犯したコーデパンの145行目の周りにあります。ここで

は私が達成しようとしているものです:

enter image description here

私はcodepenで一緒にこれを入れています。成功せず

http://codepen.io/yarnball/pen/GqbyWr?editors=1010

、私は今、次のことを試してみました:

私が使用してこれを使用してフィルタリングしてみました。すると

var LevelFilter = React.createClass({ 
    render: function(){ 
     if (!this.props.tags) return null; 
     return this.props.tags.filter(tag => tag.taglevel === this.props.targetLevel).map(tag => <a onClick={this.props.onClick}>{tag.name}</a>); 
    } 
}); 

ここで私のリターンでそれを取得しようとしている:

render: function(){ 
     ... 
     var getUniqueCategories=[]; 
       PHOTODATA.forEach(function(el){ 
     if(getUniqueCategories.indexOf(el.tag) === -1) getUniqueCategories.push(el.tag); 
    }) 

return (
      <div className="overlay-photogallery"> 
       <div className="filter-panel"><b>Tags with taglevel 1 only to be displayed</b> 
        { 
         getUniqueCategories.map(function(el,i){ 
          var boundClick = titleToSelect.bind(null,el); 
          return <LevelFilter onClick={boundClick} targetLevel={1} tags={el.tag} /> 
         }) 

        } 
        <a className="resetBtn" onClick={this.resetFilter}> Reset Filter </a> 
       </div> 

私のデータは次のようになります:

"title": "Into the Wild", 
    "tag": [ 
     { 
      "name": "Movie", 
      "taglevel": 1, 
      "id": 1 
     }, 
     { 
      "name": "Adventure", 
      "taglevel": 2, 
      "id": 30 
     }, 
     { 
      "name": "Book", 
      "taglevel": 1, 
      "id": 2 
     } 
    ], 
    "info": [] 
} 
+0

ニースフォーマットされた質問のように見えるかを確認することができ、あなたの詳細については、私はより良いアプローチのように思えるソリューション –

答えて

1

TL; DR

あなたの配列操作とあなたのリアクトコンポーネントといくつかの深刻な問題を抱えています。

リアクションは特定のトップダウン構造を提唱していることを覚えておいてください。各リアクションコンポーネントは可能な限り小道具を使用し、理想的には1つのトップレベルコンポーネントだけが状態を保持する必要があります。


前方QUICK方法:

  1. 峠ダウンすべてのデータと、各レベルのフィルタリストをユニークにしましょう。
  2. 真剣に言えば、コンポーネントを分割し、可能な限り小道具に依存させるようにしてください。
  3. 変数に意味のある名前を付けます。 elは意味がありません。あなたのケースではPHOTODATA配列のPHOTO項目を参照し、PHOTOのタグを使用してからelementを使用してもう一度他のものを意味します。一番上には行かないでくださいが、少なくとも変数が何をすべきかを特定できるようにしてください。

多くの更新された構造を持つcodepenが提供されました。その振る舞いは、あなたが探しているものではないかもしれませんが、コードとそれがどのように編成され、どのように情報がコンポーネント間で共有されて渡されるかを見てください。

http://codepen.io/anon/pen/AXGGLy?editors=1010


UPDATE は、複数のフィルタの二つの方法を更新する必要があります許可するには:

selectTag: function (tag) { 
    this.setState({ 
     displayedCategories: this.state.displayedCategories.concat([tag]) 
    }); 
} 

tagFilter: function (photo) { 
    return this.props.displayedCategories.length !== 0 && 
    this.props.displayedCategories.every(function(thisTag) { 
     return photo.tag.some(function (photoTag) { 
     return photoTag.id === thisTag.id && 
      photoTag.taglevel === thisTag.taglevel; 
     }); 
    }); 
}, 

selectTagは今それを置き換えるのではなく、displayedCategoriesアレイに追加します。

tagFilter今少なくとも1つのフィルタを適用し、それはデフォルトですべてを表示しないように(これを無効にするために、this.props.displayedCategories.length !== 0を削除)されたことを確認した後、こうして作製、各photoにすべて選択されたフィルタが存在することを確認成分添加剤。

レベルがフィルタに適用されたとき(レベルごとに1つ)にレベルを無効にしたり、適用されたフィルタのリストをボタンの色で表示したりするなど、さらに改善が加えられましたまたはタグの結果の上にリストします。

(これらの最新の変更で更新codepen)


[OK]を、あなたのcodepenを持ついくつかの問題があります。

if(getUniqueCategories.indexOf(el.tag) === -1) getUniqueCategories.push(el.tag); 

次に、146に再度それを抽出:

はまず、ライン137上には、オブジェクトからタグアレイ抽出

return <LevelFilter onClick={boundClick} targetLevel={1} tags={el.tag} /> 

とを再びレベル2

return <LevelFilter onClick={boundClick} targetLevel={2} tags={el.tag} /> 

これらの両方の場合:

return <LevelFilter onClick={boundClick} targetLevel={n} tags={el} /> 

これは、LevelFilterが有効なReactコンポーネント(配列は無効)を返さないという別の問題を明らかにします。

return this.props.tags.filter(tag => tag.taglevel === this.props.targetLevel).map(tag => <a onClick={this.props.onClick}>{tag.name}</a>); 

はあなたがなりたい場所に非常に近い試みを持っている必要があり、これらの変更後

return (
     <div>    
      { 
      this.props.tags 
       .filter(tag => tag.taglevel === this.props.targetLevel) 
       .map(tag => <a onClick={this.props.onClick}>{tag.name}</a>) 
      } 
     </div> 
    ); 

でなければなりません。

さらに調べなければならない問題があります.PHOTODATAではなくタグのリストしかないため、boundClick関数が正しく機能しないなどの問題があります。

、ちょうど最終的な考え。あなたは、あなたのリアクションコンポーネントをもう少し壊したいかもしれません。私はあなたが 、探しているものを行うことができたコンポーネントの下で

var PHOTODATA = [{ 
     "title": "Into the Wild", 
     "tag": [ 
      { 
       "name": "Movie", 
       "taglevel": 1, 
       "id": 1 
      }, 
      { 
       "name": "Adventure", 
       "taglevel": 2, 
       "id": 30 
      }, 
      { 
       "name": "Book", 
       "taglevel": 1, 
       "id": 2 
      } 
     ], 
     "info": [] 
    },{ 
     "title": "Karate Kid", 
     "tag": [ 
      { 
       "name": "Movie", 
       "taglevel": 1, 
       "id": 1 
      }, 
      { 
       "name": "Adventure", 
       "taglevel": 2, 
       "id": 30 
      }, 
      { 
       "name": "Kids", 
       "taglevel": 3, 
       "id": 4 
      } 
     ], 
     "info": [] 
    }, 
     { 
     "title": "The Alchemist", 
     "tag": [ 
      { 
       "name": "Book", 
       "taglevel": 1, 
       "id": 2 
      }, 
      { 
       "name": "Adventure", 
       "taglevel": 2, 
       "id": 30 
      }, 
      { 
       "name": "Classic", 
       "taglevel": 2, 
       "id": 4 
      }, 
      { 
       "name": "Words", 
       "taglevel": 4, 
       "id": 4 
      } 
     ], 
     "info": [] 
    }]; 


var PhotoGallery = React.createClass({ 

    getInitialState: function() { 
     return { 
     displayedCategories: [] 
     }; 
    }, 

    selectTag: function (tag) { 
     this.setState({ 
      displayedCategories: this.state.displayedCategories.concat([tag]) 
     }); 
    }, 

    resetFilter: function(){ 
     this.setState({ 
     displayedCategories: [] 
     }); 
    }, 

    render: function(){ 
     var uniqueCategories = PHOTODATA.map(function (photo) { 
      return photo.tag; // tag is a list of tags... 
     }).reduce(function (uniqueList, someTags) { 
      return uniqueList.concat(
       someTags.filter(function (thisTag) { 
       return !uniqueList.some(function(uniqueTag) { 
        return uniqueTag.id === thisTag.id && uniqueTag.taglevel === thisTag.taglevel 
       }); 
       }) 
      ); 
     }, []); 
     return (
      <div className="overlay-photogallery"> 
       <div className="filter-panel"><b>Tags with taglevel 1 only to be displayed</b> 
        <PhotoGalleryLevel level={1} tags={uniqueCategories} displayedCategories={this.state.displayedCategories} selectTag={this.selectTag} /> 
        <a className="resetBtn" onClick={this.resetFilter}> Reset Filter </a> 
       </div> 
       <div className="filter-panel"><b>Tags with taglevel 2 only to be displayed</b> 
        <PhotoGalleryLevel level={2} tags={uniqueCategories} displayedCategories={this.state.displayedCategories} selectTag={this.selectTag} /> 
       </div> 
       <div className="PhotoGallery"> 
        <PhotoDisplay displayedCategories={this.state.displayedCategories} photoData={PHOTODATA} /> 
       </div> 
      </div> 
      ); 
    } 
}); 

var PhotoGalleryLevel = React.createClass({ 
    render: function() { 
    var filteredTags = this.props.tags.filter(function (tag) { 
     return tag.taglevel === this.props.level; 
    }.bind(this)); 
    var disabled = this.props.displayedCategories.some(function (tag) { 
     return tag.taglevel === this.props.level; 
    }.bind(this)); 
    return (
     <div> 
     {filteredTags.map(function (tag){ 
      return <PhotoGalleryButton tag={tag} selectTag={this.props.selectTag} disabled={disabled} />; 
     }.bind(this))} 
     </div> 
    ); 
    } 
}); 

var PhotoGalleryButton = React.createClass({ 
    onClick: function (e) { 
    this.props.selectTag(this.props.tag); 
    }, 

    render: function() { 
    return (
     <a className={this.props.disabled} onClick={this.onClick}>{this.props.tag.name}</a> 
    ); 
    } 
}); 

var PhotoDisplay = React.createClass({ 
    getPhotoDetails: function (photo) { 
    console.log(this.props.displayedCategories, photo); 
     return (
     <Photo title={photo.title} name={photo.name} tags={photo.tag} /> 
    ); 
    }, 

    tagFilter: function (photo) { 
    return this.props.displayedCategories.length !== 0 && 
     this.props.displayedCategories.every(function(thisTag) { 
     return photo.tag.some(function (photoTag) { 
      return photoTag.id === thisTag.id && 
      photoTag.taglevel === thisTag.taglevel; 
     }); 
     }); 
    }, 

    render: function() { 
    return (
     <div> 
     {this.props.photoData.filter(this.tagFilter).map(this.getPhotoDetails)} 
     </div> 
    ); 
    } 
}); 

var Photo = React.createClass({ 
    getTagDetail: function (tag){ 
     return (
     <li>{tag.name} ({tag.taglevel})</li> 
    ); 
    }, 

    sortTags: function (tagA, tagB) { 
    return tagA.taglevel - tagB.taglevel; 
    }, 

    render: function(){ 
     return (
      <div className="photo-container" data-title={this.props.title} > 
       {this.props.title} 
       <ul> 
        {this.props.tags.sort(this.sortTags).map(this.getTagDetail)} 
       </ul> 
      </div> 
     ); 
    } 
}); 

ReactDOM.render(<PhotoGallery />, document.getElementById('main')); 
+0

を見つけるのを助けます。有難うございます。私はそれをよりよく理解しています。 1つの問題で機能しています。すなわち、フィルタ/タグは、互いに積み重ねてください。 IEではレベル1から1つのフィルタを選択し、レベル2からはBOTHタグに関連する項目のみを表示します。これを行うには何が必要ですか? – Ycon

+0

ここで重要な点は、 'selectTag'と' tagFilter'関数です。現在、 'selectTag'は、' this.setState({displayedCategories:this.state.displayedCategories.concat([tag])}) ')')を追加することができるときに常に_displayedCategories_を置き換え、 'tagFilter'はできるときに_some_操作を行います_every_、しかしそれはかなり正しくないかもしれません。私は答えを更新します。 –

+0

優れています。ありがとうございました。それはほぼそこにある!タグが選択されていない場合は、すべてのタグを表示します。しかし、タグがクリックされると、下の階層に結果が存在しない「タグ」を**非表示にします**。これはどのように達成されますか? – Ycon

1

反応し、ここで私が何をやったかです:参考


は、ここcodepenからリスト完全なコードですiはtaglevel1作成したPHOTODATA配列からコード、

I)、taglevel2アレイ 1レンダリング方法Aで最初から始まった。

ii)showLevel1,showLevel2の2つの行に示します。

iii)タグ項目をクリックすると、​​関数が呼び出され、データがフィルタリングされ、filterData状態に保存されます。

import React, { Component } from 'react'; 
import { pluck } from 'underscore'; 

class Router extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
    filterData: [], 
    }; 
    this.filterArray = []; 
    this.PHOTODATA = [{ 
    "title": "Into the Wild", 
    "tag": [ 
     { 
      "name": "Movie", 
      "taglevel": 1, 
      "id": 1 
     }, 
     { 
      "name": "Adventure", 
      "taglevel": 2, 
      "id": 30 
     }, 
     { 
      "name": "Book", 
      "taglevel": 1, 
      "id": 2 
     } 
    ], 
    "info": [] 
},{ 
    "title": "Karate Kid", 
    "tag": [ 
     { 
      "name": "Movie", 
      "taglevel": 1, 
      "id": 1 
     }, 
     { 
      "name": "Adventure", 
      "taglevel": 2, 
      "id": 30 
     }, 
     { 
      "name": "Kids", 
      "taglevel": 3, 
      "id": 4 
     } 
    ], 
    "info": [] 
}, 
    { 
    "title": "The Alchemist", 
    "tag": [ 
     { 
      "name": "Book", 
      "taglevel": 1, 
      "id": 2 
     }, 
     { 
      "name": "Adventure", 
      "taglevel": 2, 
      "id": 30 
     }, 
     { 
      "name": "Classic", 
      "taglevel": 2, 
      "id": 4 
     }, 
     { 
      "name": "Words", 
      "taglevel": 4, 
      "id": 4 
     } 
    ], 
     "info": [] 
}]; 
} 
handleClick(item) { 
const findItem = this.filterArray.indexOf(item); 
if (findItem === -1) { 
    this.filterArray.push(item); 
} else { 
    this.filterArray.pop(item); 
} 
const filterData = []; 
if(this.filterArray.length) { 
    this.PHOTODATA.map((item) => { 
     const data = pluck(item.tag, 'name'); 
     let count = 0; 
     // console.log(data); 
     this.filterArray.map((filterItem) => { 
     const find = data.indexOf(filterItem); 
     if(find !== -1) { 
      count++; 
     } 
     }); 
     if(count === this.filterArray.length) { 
      filterData.push(item); 
     } 
    }); 
} 
console.log(this.filterArray); 
this.setState({ filterData }); 
} 
render() { 
const taglevel1 = []; 
const taglevel2 = []; 
this.PHOTODATA.map((item) => { 
     item.tag.map((tagItem) => { 
      if(tagItem.taglevel === 1) { 
       const find = taglevel1.indexOf(tagItem.name); 
       if(find === -1) { 
        taglevel1.push(tagItem.name); 
       } 
      } else { 
       const find = taglevel2.indexOf(tagItem.name); 
       if(find === -1) { 
        taglevel2.push(tagItem.name); 
       } 
      } 
     }); 
}); 
const showLevel1 = (item, index) => { 
    return <span onClick={this.handleClick.bind(this, item)}> {item} </span> 
}; 
const showLevel2 = (item, index) => { 
    return <span onClick={this.handleClick.bind(this, item)}> {item} </span> 
}; 
const showData = (item, index) => { 
    return <div>{item.title}</div> 
}; 
return (<div> 
    <ul>Tag Level 1: {taglevel1.map(showLevel1)}</ul> 
    <ul>Tag Level 2: {taglevel2.map(showLevel2)}</ul> 
    <div>Movie Title: {this.state.filterData.map(showData)}</div> 
</div>); 
}} 

、ここであなたは私の出力は

enter image description here

関連する問題