Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/403.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 不变性的好处是什么?_Javascript_Reactjs_Immutability - Fatal编程技术网

Javascript 不变性的好处是什么?

Javascript 不变性的好处是什么?,javascript,reactjs,immutability,Javascript,Reactjs,Immutability,我使用React来呈现长的可滚动项目列表(+1000)。我找到了能帮我的人 因此,在查看列表时,我应该将列表作为道具传递给我的项目列表组件。让我大吃一惊的是,在这个例子中,列表是不可变的(使用),我想这是有意义的,因为道具就是这样工作的——但是如果我想更改行项目,我不能更改它的状态,因为行将使用列表重新排序,从而抛出状态 我试图做的是在单击某一行时高亮显示该行,如果我从视图中滚出来并再次回到视图中,该行仍会高亮显示。现在,如果列表不是不可变的,我可以更改表示该行的对象,高亮显示的行将保持高亮显示

我使用React来呈现长的可滚动项目列表(+1000)。我找到了能帮我的人

因此,在查看列表时,我应该将列表作为道具传递给我的项目列表组件。让我大吃一惊的是,在这个例子中,列表是不可变的(使用),我想这是有意义的,因为道具就是这样工作的——但是如果我想更改行项目,我不能更改它的状态,因为行将使用列表重新排序,从而抛出状态

我试图做的是在单击某一行时高亮显示该行,如果我从视图中滚出来并再次回到视图中,该行仍会高亮显示。现在,如果列表不是不可变的,我可以更改表示该行的对象,高亮显示的行将保持高亮显示,但我不确定这样做是否正确。除了改变道具,还有其他解决办法吗

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')
);
class ItemsList扩展了React.Component{
(...)
render(){
(...)    
返回(
)
}
_行渲染器({index}){
const{list}=this.props;
常量行=列表[索引];
返回(
)
}
}
类行扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
突出显示:错误
};
}
handleClick(){
this.setState({突出显示:true});
列表[this.props.index].color='yellow';
}
render(){
让color=list[this.props.index].color;
返回(
这是第{This.props.index}行
)
}  
}
常量列表=[1000+个对象的数组];
ReactDOM.render(
,
document.getElementById('app')
);

如果一次只渲染1000个列表中的10个,那么记住高亮显示标志的唯一方法是将其存储在父状态,即1000个列表中

如果没有不变性,这将类似于:

// 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.
对于不变性,您将执行非常类似的操作:

// 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 );
仅当对象不包含更多嵌套对象时,上述操作才有效。
我不熟悉immutable.js,但我相信他们有很好的方法来更恰当地处理这个问题


react中不变性的理由是,您可以可靠且透明地处理状态更改(react的生命周期方法也期望这些更改)。有很多关于“为什么nextState==this.state”的问题,答案归结为“没有保持状态和道具不变,把事情搞砸了”

我不完全确定你问的问题是什么,正如您所问的两个截然不同的问题。如果我更改行的状态,情况就是这样:您是对的,不太清楚……我想突出显示列表中的一些行。我的解决方案是更改我在组件中用作道具的列表。我不认为我应该这样做,但我不知道为什么。当你不想改变状态时,不变性是好的。当我们生活在一个状态不断变化的世界中时,我觉得完全代码不变性的想法是幼稚和不现实的。但是,如果一行高亮显示或未高亮显示,则感觉应该处于行组件的状态。或者我可以将高亮显示行的索引置于ItemList组件的状态。