2016-08-22 20 views
4

我正在處理簡單的流應用程序。我有帖子列表,這個列表可以接收更新,它將顯示在最上面。如何添加新元素而不用React渲染整個列表

問題是在每個新帖子收到React重新呈現元素的整個列表。我爲它做了一個簡單的例子。

有什麼辦法可以避免這種行爲? 我見過動態子女關於React文檔的主題,但在例子中,如您所見,無論如何我都要更新所有子項。

class Post extends React.Component { 
 
    render() { 
 
    console.log('rerendered post', this.props.reactKey); 
 
    return (
 
     <li>{this.props.post.text}</li> 
 
    ); 
 
    } 
 
} 
 

 
class App extends React.Component { 
 

 
    constructor(props) { 
 
    super(props); 
 
    this.state = {posts: [ 
 
     {id: '00001', text: 'First one'}, 
 
     {id: '00002',text: 'Second one'}, 
 
     {id: '00003',text: 'Third one'} 
 
    ]}; 
 
    } 
 

 
    addPost() { 
 
    const posts = this.state.posts; 
 
    posts.unshift({id: '00004', text: 'New post'}); 
 
    this.setState({posts: posts}); 
 
    } 
 

 
    render() { 
 
    return (
 
     <div> 
 
     <button onClick={this.addPost.bind(this)}>Add Post</button> 
 
     <ul> 
 
      {this.state.posts.map((post, index) => { 
 
      return (<Post post={post} key={post.id} reactKey={index} />); 
 
      })} 
 
     </ul> 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 

 
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<body> 
 
    <div id="root"></div> 
 
</body>

溶液

問題是,我使用的.MAP函數的指數爲每個列表組件,而不是唯一的密鑰的密鑰。因爲在添加新元素以列出所有索引更改爲+1之後,所以第一個帖子成爲第二個,所有我的帖子都重新呈現。 因此,首先檢查您是否在所有列表元素中使用唯一鍵:-)

+0

沒有什麼錯渲染得到多次調用,陣營只會更新的東西,實際上改變DOM。渲染被調用到每個組件上以確定是否有任何變化。如果你確實知道你的組件中它甚至應該嘗試調用渲染(我重申很好),你可以使用'shouldComponentUpdate' – azium

+0

問題是我不需要重新渲染舊帖子,因爲有一些函數與API調用等 我希望他們只是保持原樣,只添加和呈現新帖子。 –

+0

然後你必須使用'shouldComponentUpdate'來確定是否有相關的道具已經改變 – azium

回答

2

需要完成一次的工作應該在保證只運行一次的生命週期方法中完成,例如componentDidMount。如文檔所示:

如果您想與其他JavaScript框架集成,使用setTimeout或setInterval設置定時器,或發送AJAX請求,請使用此方法執行這些操作。

我添加記錄到componentDidMount在你的代碼片段顯示渲染髮生很多次,但componentDidMount叫每個實例一次。

class Post extends React.Component { 
 
    componentDidMount() { 
 
    console.log('mounted post', this.props.id); 
 
    } 
 

 
    render() { 
 
    console.log('rerendered post', this.props.id); 
 
    return (
 
     <li>{this.props.post.text}</li> 
 
    ); 
 
    } 
 
} 
 

 
class App extends React.Component { 
 

 
    constructor(props) { 
 
    super(props); 
 
    this.nextId = 4; 
 
    this.state = { 
 
     posts: [ 
 
     {id: 1, text: 'First one'}, 
 
     {id: 2,text: 'Second one'}, 
 
     {id: 3,text: 'Third one'}, 
 
     ], 
 
    }; 
 
    } 
 

 
    addPost() { 
 
    const posts = this.state.posts; 
 
    posts.unshift({id: this.nextId, text: 'Post ' + this.nextId}); 
 
    this.nextId++; 
 
    this.setState({posts: posts}); 
 
    } 
 

 
    render() { 
 
    return (
 
     <div> 
 
     <button onClick={this.addPost.bind(this)}>Add Post</button> 
 
     <ul> 
 
      {this.state.posts.map((post, index) => { 
 
      return (<Post post={post} key={post.id} id={post.id} />); 
 
      })} 
 
     </ul> 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 

 
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<body> 
 
    <div id="root"></div> 
 
</body>

+0

謝謝Ross。實際的問題是(因爲我是React的新手),我沒有在所有列表元素中使用唯一鍵。我只使用了map函數的索引值,當然在添加新元素之後列出了所有元素已經重新渲染,因爲每個元素的關鍵值已被更改。 –