2017-05-25 103 views
0

我遇到了更新部分状态的问题,该状态是传递给组件的子项的列表。与状态列表反应,如何设置新状态?

我将一个列表传递给一个孩子,但却无法更新该列表并让孩子反映新的状态;

<ItemsClass items={this.state.items1} /> 

当我改变的this.state.items1值时,部分不以新的价值呈现。但是,如果我改变已经存在的数组(不是替换它新建一个新的空数组),那么该组件会根据我的意愿呈现;如果我改变了已经存在的数组(而不是替换它新建一个新的空数组),则该组件呈现为我想要的;

this.setState(state => { clearArray(state.items1); return state; }); 

这意味着在状态更新功能不是纯的,起反应状态是应该的。

HTML;

<div id='app'></div> 

对JS;

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

    this.state = {items: props.items}; 
    } 

    render() { 
    var items = this.state.items.map(it => <div key={it.id}>{it.text}</div>); 
    return(
     <div>{items}</div> 
    ); 
    } 
} 

function ItemsFunction(props) { 
    var items = props.items.map(it => <div key={it.id}>{it.text}</div>); 
    return(
     <div>{items}</div> 
    ); 
} 

class App extends React.Component { 
    constructor(props){ 
    super(props); 
    var items = [{id:1, text: 'item 1'}, {id: 2, text: 'item 2'}]; 

    this.state = { 
     items1: items.slice(), 
     items2: items.slice(), 
     items3: items.slice() 
    }; 
    this.clearLists = this.clearLists.bind(this); 
    } 

    clearLists() { 
    // for items1 and items2, clear the lists by assigning new empty arrays (pure). 
    this.setState({items1: [], items2: []}); 

    // for items3, change the already existing array (non-pure). 
    this.setState(state => { 
     while (state.items3.length) { 
     state.items3.pop(); 
     } 
    }) 
    } 

    render() { 
    return (
     <div> 
     <button onClick={this.clearLists}>Clear all lists</button> 
     <h2>Items rendered by class, set list to new empty array</h2> 
     <ItemsClass items={this.state.items1} /> 
     <h2>Items rendered by class, empty the already existing array</h2> 
     <ItemsClass items={this.state.items3} /> 
     <h2>Items rendered by function</h2> 
     <ItemsFunction items={this.state.items2} /> 
     </div> 
    ); 
    } 
} 

ReactDOM.render(<App />, document.getElementById('app')); 

试一下codepen

看起来ItemsClass不会更新,即使它是在父更改中使用<ItemsClass items={this.state.items1}/>this.state.items1创建的。

这是预期的行为?我如何从家长更新ItemsClass孩子的状态? 我我错过了什么?这种行为似乎很容易出错,因为很容易假设孩子应该遵循新的状态,即创建孩子时传入的方式。

回答

2

您正在将ItemsClass的道具复制到组件的初始化状态 - 当道具更改时不重置状态,因此组件的更新不会显示。引用docs

请注意这种模式,因为状态不会随任何道具更新而更新。不是将道具同步到状态,而是经常想要提升状态。

如果你的组件必须做一些事情时,道具的变化,您可以使用componentWillReceieveProps生命周期挂钩这样做(请注意,它不会运行时组件安装初期,仅在随后的道具更新)。

也就是说,你在这里复制道具的原因是零(而且老实说很少有一个很好的理由这样做) - 直接使用道具,就像你在做ItemsFunction一样,一切都会保持同步:

class ItemsClass extends React.Component { 
    render() { 
    var items = this.props.items.map(it => <div key={it.id}>{it.text}</div>); 
    return(
     <div>{items}</div> 
    ); 
    } 
} 

这是你Codepen的工作版本:http://codepen.io/anon/pen/JNzBPV