2016-10-12 2 views
2

連絡先を表示するテーブルがあり、連絡先をファーストネームで並べ替える必要があります。連絡先配列はreduxストアから来ていますが、これは小道具を経由して来ますが、ローカルのUI状態であるため、ローカルの状態でその連絡先のソート方法を保持する必要があります。これをどのように達成するのですか?私は今のところ連絡先をcomponentWillReceivePropsに置いていますが、何らかの理由でそれが変わったときにその小道具を受け取っていません。 reducexストアの状態が変わるたびに、ローカル状態を更新するにはどうすればよいですか?私が今見ている問題はcontactRows, filteredSortedContacts, sortedContactsが一回ごとのTableRowのために、複数回呼び出されていることである同じ反応成分に還元状態と一緒に局所状態をどのように使用するのですか?

import React, {Component} from 'react' 
import TableRow from './TableRow' 

class Table extends Component { 
    constructor (props) { 
    super(props) 
    this.state = { sortBy: "fistName" } 
    } 
    sortContacts (parameter) { 
    console.log('in sortContacts') 

    this.setState({ sortBy: parameter }) 
    } 
    sortedContacts() { 
    console.log('in sortedContacts') 

    const param = this.state.sortBy 
    return (
     this.props.data.contacts.sort(function (a, b){ 
     if (!a.hasOwnProperty(param)){ 
      a[param] = " "; 
     } 
     if (!b.hasOwnProperty(param)){ 
      b[param] = " "; 
     } 
     const nameA = a[param].toLowerCase(), nameB = b[param].toLowerCase(); 
     if (nameA > nameB) { 
      return 1; 
     } else { 
      return -1; 
     } 
     }) 
    ) 
    } 
    filteredSortedContacts() { 
    console.log('in filteredSortedContacts') 

    const filterText = this.props.data.filterText.toLowerCase() 
    let filteredContacts = this.sortedContacts() 
    if (filterText.length > 0) { 
     filteredContacts = filteredContacts.filter(function (contact){ 
     return (
      contact.hasOwnProperty('lastName') && 
      contact.lastName.toLowerCase().includes(filterText) 
     ) 
     }) 
    } 
    return filteredContacts 
    } 
    contactRows() { 
    console.log('in contactRows') 
    return this.filteredSortedContacts().map((contact, idx) => 
     <TableRow contact={contact} key={idx}/> 
    ) 
    } 
    render() { 
    return (
     <div className="table-container"> 
     <table className="table table-bordered"> 
      <thead> 
      <tr> 
       <th className="th-cell" onClick={this.sortContacts.bind(this, "firstName")}>First Name</th> 
       <th onClick={this.sortContacts.bind(this, "lastName")}>Last Name</th> 
       <th>Date of Birth</th> 
       <th>Phone</th> 
       <th>Email</th> 
       <th>Notes</th> 
      </tr> 
      </thead> 
      <tbody> 
      {this.contactRows()} 
      </tbody> 
     </table> 
     </div> 
    ) 
    } 
} 

export default Table 

をフィルタリング含み、現在のコードの

const Table = React.createClass({ 
    getInitialState() { 
    return {contacts: []} 
    }, 
    componentWillReceiveProps() { 
    this.setState({ contacts: this.props.data.contacts}) 
    }, 
    sortContacts (parameter, e){ 
    ... 
    }, 
    render() { 
    return (
     <table> 
     <thead> 
      <tr> 
      <th onClick={this.sortContacts.bind(this, "firstName")}>First Name</th> 
      </tr> 
     </thead> 
     <tbody> 
      {contactRows} 
     </tbody> 
     </table> 
    ) 
    } 
}) 

更新。私は体内で一度だけ​​と呼んでいるなら、どうしてこのようなことが起こるのか分かりません。

+0

'sortContants'のレデューサーと内容を表示します。 – luboskrnac

答えて

2

componentWillReceiveProps()メソッドは初期レンダリングのために呼び出されません。彼らはちょうどそれが本当に明確な小道具ことを確認するために、あなたが小道具のinitialContactsに名前を示唆React docs

getInitialState() { 
    return { 
    contacts: this.props.data.contacts 
    } 
} 

:何ができるか、あなただけの初期データとして小道具からのデータを使用する場合は、のようなものです'目的は内部的に何かを初期化することだけです。

this.props.contactsが変更されたときに更新したい場合は、componentWillReceiveProps()と同じように使用できます。しかし、私はそれが最良のアイデアだとは確信していません。ドキュメントから:getInitialState状態を生成するための小道具を使って

は、多くの場合、実際のデータがある、すなわち「真のソース」の 重複につながります。 getInitialStateは、コンポーネントが最初に作成されたときにのみ呼び出されるため、 が作成されます。 が作成されます。

可能であれば、オンザフライで値を計算して、後で が同期しなくなり、メンテナンスに問題が発生しないようにしてください。

6

あなたの還元型ストアとローカルストアの両方を使用するアプローチは正しいです。

あなたのコンポーネントのreduxストアから状態を複製しようとしないでください。小道具を介してそれを参照してください。

代わりに、ローカルに保存されたsortByパラメータを還元された格納された連絡先に適用して、その場で値を計算するsortedContacts関数を作成します。

const Table extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     sortBy: 'id' // default sort param 
    } 
    } 

    sortContacts(param) { 
    this.setState({ sortBy: param}) 
    } 

    sortedContacts() { 
    return this.props.contacts.sort(...); // return sorted collection 
    } 

    render() { 
    return (
     <table> 
     <thead> 
      <tr> 
      <th onClick={() => this.sortContacts("firstName")}>First Name</th> 
      </tr> 
     </thead> 
     <tbody> 
      {this.sortedContacts()} 
     </tbody> 
     </table> 
    ) 
    } 
} 
+1

うわー、これはクールです!そのため、ローカル状態にソートされた連絡先の配列を保持させる代わりに、ソートを行うために必要なパラメータが保持されます。このパラメータが変更されても、自動的に再レン​​ダリングが行われ、#sortedContactsを再度呼び出しますか?私は、オートレンダリングは、状態が変化したときにのみ発生し、状態の変化に依存するメソッドではなく、レンダリングが必要な状態があると考えました。 – stackjlei

+0

redux州の複製を作成してソートするよりも、これを行うほうが良いのはなぜですか? – stackjlei

+4

真理のソースが1つだけの場合は、同期コードは必要ありません。あなたの場合、ソートだけでなくフィルタリング、変形なども同じ方法で簡単に適用できます。 –

関連する問題