我试图弄清楚如何渲染一组div,而不会在添加新的div时重新渲染整个列表。
所以我有一个有状态的组件。在所说的有状态组件内部,我有一个函数,A,获取帖子ID的列表,B,向每个帖子ID的请求,并将结果推送到数组。像这样:
getArticles = () => {
axios.get(`${api}/topstories.json`)
.then(items => {
let articles = items.data;
let init = articles.slice(0,50);
init.forEach(item => {
axios.get(`${post}/${item}.json`)
.then(article => {
this.setState({ articles: [...this.state.articles, article.data]});
});
})
});
}
然后,我有了第二个函数,该函数接收此信息并将其输出到帖子列表。像这样:
mapArticles = () => {
let articles = this.state.articles.map((item, i) => {
let time = moment.unix(item.time).fromNow();
return(
<section className="article" key={i}>
<Link className="article--link" to={`/posts/${item.id}`}/>
<div className="article--score">
<FontAwesomeIcon icon="angle-up"/>
<p>{item.score}</p>
<FontAwesomeIcon icon="angle-down"/>
</div>
<div className="article--content">
<div className="article--title">
<h1>{item.title}</h1>
</div>
<div className="article--meta">
{item.by} posted {time}. {item.descendants ? `${item.descendants} comments.` : null}
</div>
</div>
<div className="article--external">
<a href={item.link} target="_blank">
<FontAwesomeIcon icon="external-link-alt"/>
</a>
</div>
</section>
)
});
return articles;
}
然后我在render函数中使用{this.mapArticles()}
返回适当的信息。
但是,每当应用程序加载新数据时,它都会重新呈现整个列表,从而造成大量麻烦。也就是说,当第一个请求完成时,它将呈现第一个div。当第二个请求完成时,它将重新渲染第一个div并呈现第二个div。当第三个请求完成时,它将重新呈现第一个和第二个,并呈现第三个。
有没有一种方法可以让React识别出具有该键的div已经存在,并且在状态改变并且函数再次运行时应该忽略它?
答案 0 :(得分:0)
我仅用于渲染新零件的一种技术是保留已绘制的obj的缓存映射,因此在render方法中,我仅渲染新的传入元素。
这里是一个示例: 看看https://codesandbox.io/s/wq2vq09pr7
在此代码中,您可以看到List具有一个缓存数组和render方法 只画新的数组
class RealTimeList extends React.Component {
constructor(props) {
super(props);
this.cache = [];
}
renderRow(message, key) {
return <div key={key}>Mesage:{key}</div>;
}
renderMessages = () => {
//let newMessages=this,props.newMessage
let newElement = this.renderRow(this.props.message, this.cache.length);
this.cache.push(newElement);
return [...this.cache];
};
render() {
return (
<div>
<div> Smart List</div>
<div className="listcontainer">{this.renderMessages()}</div>
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = { message: "hi" };
}
start = () => {
if (this.interval) return;
this.interval = setInterval(this.generateMessage, 200);
};
stop = () => {
clearTimeout(this.interval);
this.interval = null;
};
generateMessage = () => {
var d = new Date();
var n = d.getMilliseconds();
this.setState({ title: n });
};
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={this.start}> Start</button>
<button onClick={this.stop}> Stop</button>
<RealTimeList message={this.state.message} />
</div>
);
}
}
答案 1 :(得分:0)
如果物品是同时到达的,请等到所有物品都拿到后再渲染:
getArticles = () => {
axios.get(`${api}/topstories.json`)
.then(items => {
let articles = items.data;
let init = articles.slice(0, 50);
Promise.all(init.map(item => axios.get(`${post}/${item}.json`)).then(articles => {
this.setState({
articles
});
})
});
}
如果您真的想在获取项目后立即渲染,则可以引入一个实用组件,该组件可以在promise分解时进行渲染。
class RenderOnResolve extends React.Component {
state = null
componentDidMount() {
this.props.promise.then(data => this.setState(data))
}
render() {
return this.state && this.props.render(this.state);
}
}
// usage:
<RenderOnResolve promise={promise} render={this.articleRenderer}/>