2016-05-25 3 views
2

私はReactを使ってアイテムの長いスクロール可能なリスト(+1000)をレンダリングしています。私はこれを助けるのにReact Virtualizedを見つけました。不変性のメリットは何ですか?

だから、example hereを見て、私はアイテムリストコンポーネントの小道具としてそのリストを渡すべきです。私を引き裂くのは、この例ではリストが不変(Immutable.jsを使用しています)です。これは小道具の仕組みなので意味があると思いますが、行アイテムを変更したい場合は、行はリストを使用して再レンダリングされ、状態をスローします。

私がしようとしているのは、クリックしたときに行を強調表示して、ビューからスクロールして再びその行に戻すと、強調表示されます。今、リストが不変でない場合、私は行を表すオブジェクトを変更することができ、強調表示された行は強調表示されたままになりますが、それが正しい方法であるかどうかはわかりません。この小道具を突然変異させる以外の解決策はありますか?

class ItemsList extends React.Component { 
    (...) 
    render() { 
    (...)  
    return(
     <div> 
     <VirtualScroll 
      ref='VirtualScroll' 
      className={styles.VirtualScroll} 
      height={virtualScrollHeight} 
      overscanRowCount={overscanRowCount} 
      noRowsRenderer={this._noRowsRenderer} 
      rowCount={rowCount} 
      rowHeight={useDynamicRowHeight ? this._getRowHeight : virtualScrollRowHeight} 
      rowRenderer={this._rowRenderer} 
      scrollToIndex={scrollToIndex} 
      width={300} 
     /> 
     </div> 
    ) 
    } 
    _rowRenderer ({ index }) { 
    const { list } = this.props; 
    const row = list[index]; 

    return (
     <Row index={index} /> 
    ) 
    } 
} 


class Row extends React.Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     highlighted: false 
    }; 
    } 

    handleClick() { 
    this.setState({ highlighted: true }); 

    list[this.props.index].color = 'yellow'; 
    } 

    render() { 
    let color = list[this.props.index].color; 

    return (
     <div 
     key={this.props.index} 
     style={{ height: 20, backgroundColor: color }} 
     onClick={this.handleClick.bind(this)} 
     > 
     This is row {this.props.index} 
     </div> 
    ) 
    } 
} 

const list = [array of 1000+ objects]; 

ReactDOM.render(
    <ItemsList 
    list={list} 
    />, 
    document.getElementById('app') 
); 
+0

私はあなたに何が疑問ですか?あなたは2つの異なる質問をしたように、尋ねています。 – evolutionxbox

+0

これは、行の状態を変更すると、次のようになります。http://output.jsbin.com/hopuhuhihu – schwift

+0

あなたは正しいとは言えません。リスト内の行を強調表示したいのですが。私の解決策は、コンポーネント内の小道具として使用するリストを変更することです。私はこれをやるべきだとは思わないが、なぜか分からない。 – schwift

答えて

0

あなただけのは、一度に1000のリストのうち10を言わせてレンダリングする場合は、強調表示フラグを記憶する唯一の方法は、1000年のリストである親状態、それを格納することです不変性がなければ、このようなものだろう

:。

// make a copy of the list 
var list = this.state.list.slice(); 
// make a copy of the object to update 
var newObject = Object.assign({}, list[itemToChange]); 
// update the object copy 
newObject.highlighted = true; 
// insert the new object into list copy 
list[itemToChange] = newObject; 
// update state with the new list 
this.setState({ list : list); 
:不変で

// make a copy of the list - NB: this will not copy objects in the list 
var list = this.state.list.slice();  
// so when changing object, you are directly mutating state 
list[itemToChange].highlighted = true; 
// setting state will trigger re-render 
this.setState({ list: list }); 
// but the damage is already done: 
// e.g. shouldComponentUpdate lifecycle method will fail 
// will always return false, even if state did change. 

、あなたは非常に類似した何かをやっているだろう

上記はオブジェクトに入れ子オブジェクトが含まれていない場合にのみ機能します。
私はimmutable.jsに精通していませんが、もっと適切に対処するための優れた方法があると確信しています。

反応が不変であるという議論は、あなたが確実に、そして透明に状態変化(反応のライフサイクルメソッドが期待している)を行うことができるということです。 "なぜnextState == this.state"の変種で、 "状態を保持しておらず、不器用な不具合を消さない"という回答がたくさんあるので、多くの質問があります。

関連する問題