在基本的React应用程序中重新渲染组件的问题
我正在构建一个基本的React应用程序,该应用程序呈现数组中书籍的列表,并具有将另一个书籍对象推送到数组的表单。我在考虑修改book数组是对道具的一种改变,这会导致Post
组件重新渲染,但是我不能让Post
重新渲染,除非我强制使用链接和导航回来手动强制它。我相信我已经附加了所有相关的组件以及书籍数组。我使用create-react-app来设置React环境。 React版本 - 15.4.1。非常感谢您提供的任何帮助!在基本的React应用程序中重新渲染组件的问题
编辑: 我已经重构了一点,创造了一个GitHub库,使一切更清晰。
import React from 'react'
import ReactDOM from 'react-dom'
import {Router, Route, IndexRoute, hashHistory} from 'react-router'
import App from './App'
import Display from './Display'
import Content from './Content'
//stylesheet
import './index.css'
//import posts array
import postsArray from './postsArray'
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={App}>
<IndexRoute component={Display} entries={postsArray}></IndexRoute>
<Route path="view/:id" component={Content} entries={postsArray}></Route>
</Route>
</Router>,
document.getElementById('root')
);
import React, {Component} from 'react'
import Post from './Post'
class Display extends Component {
constructor(props) {
super(props)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit(event) {
this.props.route.entries.push({
title: this.titleInput.value,
author: this.authorInput.value,
body: this.bodyText.value
})
event.preventDefault()
}
render() {
return(
<div>
<Post entries={this.props.route.entries}/><br /> <br />
<form onSubmit={this.handleSubmit}>
<label>
Title:<br />
<input type={"text"} ref={(titleInput) => this.titleInput = titleInput} className="input" />
</label><br />
<label>
Author:<br />
<input type="text" ref={(authorInput) => this.authorInput = authorInput} className="input" />
</label> <br />
<label>
Body:<br />
<textarea ref={(bodyText) => this.bodyText = bodyText} className="textAreaInput"/>
</label> <br />
<input type="submit" value="Submit" />
</form>
</div>
)
}
}
export default Display
import React, {Component} from 'react'
import {Link} from 'react-router'
class Post extends Component {
constructor(props) {
super(props)
console.log("insinde post initial", this.props.entries)
}
render() {
return (
<div className="postsWrapper">
{this.props.entries.map((entry, index) => (
<div key={index} className="divMargin">
<Link to={"view/" + index } className="postLink">
<h1 className="postH titleFont">{entry.title}</h1>
<h2 className="authorFont authorMargin">{entry.author}</h2>
</Link>
</div>
))}
</div>
)
}
}
export default Post
var posts = [
{
title: "A Walk in the Woods",
author: "Bill Bryson",
body: "A very enjoyable book!"
},
{
title: "Bridge Over The River Kwai",
author: "Pierre Boulle",
body: "I have never read this book. Not ever."
},
{
title: "Do Not Sell at Any Price",
author: "Amanda Petrusich",
body: "Will you please please please give me this book when you're done?"
},
{
title: "Just Kids",
author: "Patti Smith",
body: "This is a national book award winner! Wow!"
}
]
export default posts
我能解决这个问题(和学习的东西)通过使用setState
和.concat
,而不是直接与.push
变异的阵列。最终的解决方案是这样的:
this.setState({
entries: this.state.entries.concat([{
title: this.titleInput.value,
author: this.authorInput.value,
body: this.bodyText.value
}])
})
实际更改是在github回购如果感兴趣。
感谢@Stanley Luo对他的调试帮助。
默认情况下,如果道具(在你的情况,帖子阵列)的变化,相关的组件应无故障更新。
但由于您的Post
组件拒绝更新,我建议您使用shouldComponentUpdate()进行检查,检查道具是否相应更新。
shouldComponentUpdate
总是在render方法之前被调用,并且能够定义是否需要重新渲染或可以跳过。
componentWillUpdate
只要shouldComponentUpdate返回true就会被调用。任何通过this.setState进行的状态更改都是不允许的,因为此方法应严格用于准备即将到来的更新,而不会触发更新本身。
如果您不熟悉生命周期方法,请检查此article。
在你的情况下,尝试
shouldComponentUpdate(nextProps, nextState) {
return nextProps.entries.length !== this.props.entries.length;
}
componentWillUpdate(nextProps, nextState) {
// posts array did change, do something
}
感谢您的帮助!我试着实现了不会触发重新渲染的shouldComponentUpdate方法。我在回车上面放了一个console.log,以查看它何时被调用,但无法获取任何日志,就好像shouldComponentUpdate从未被调用过。 –
@HarryZumwalt这意味着你的道具和状态都不会改变;很可能它是通过路由器获得的道具没有相应更新。尝试一种获取posts数组的新方法 - 我推荐使用'componentWillMount()'生命周期方法从'Redux store'中获取数组。 –
嗯有趣。我已经尝试直接通过“Display”(不是路由器)通过道具引入它。我也试着设置状态等于构造函数/ componentWillMount挂钩内的数组,但没有成功。我确定Redux不应该是必需的。难住这个。 –
在路由器上使用“条目”对我来说看起来有点不寻常。你能否进一步解释为什么你想以这种方式填充帖子数组? –
而且,由于您正在记录帖子数组,您的数组道具可以在Post组件中成功更新吗? –
我有点擅自决定从路由器传递阵列作为道具。这可能不是最好的决定,但即使我通过显示组件中的道具作为道具,也会遇到同样的问题。另外,Post组件实际上只负责渲染每个Post,并且这些内容与更新发生的形式没有关系,但是我觉得它应该仍然会因道具变化而重新渲染。 –