我正在开发简单的流应用程序。我有一个帖子列表,这个列表可以接收更新,更新将显示在上面。
问题是在每个新帖子上接收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>
解决方案
问题是我使用了索引。映射函数是每个列表组件的键,而不是唯一键。因为在添加新元素以列出所有索引后,第一篇文章变为第二篇,所以我的所有文章都重新呈现。因此,首先,检查是否在所有列表元素中使用唯一键:-)
只需要完成一次的工作应该在保证只运行一次的生命周期方法中完成,如componentDidMount
。正如文件建议的那样:
如果您想与其他JavaScript框架集成,使用setTimeout或setInterval设置计时器,或者发送AJAX请求,请在此方法中执行这些操作。
我在您的代码片段中添加了日志记录到组件迪迪蒙特
,以显示呈现发生了多次,但是组件迪迪蒙特
每个实例只调用一次。
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>