【发布时间】:2020-01-02 11:25:30
【问题描述】:
当使用PureComponents 时,您拥有优于功能组件的优势,即在父更新时组件并不总是呈现。它实际上只在组件 props 发生变化时才会呈现,在本例中仅在您更改输入时才会呈现。
如何将对象传递给 PureComponent 而不会破坏使用此类组件的所有优势?
这是否意味着一旦你有一个你期望它是 object 类型的 prop,最好让你的组件正常工作?
我添加了一个例子来说明我的意思......(可能你需要在新窗口中打开它,因为有很多不同的孩子)
class TestPureComponent extends React.PureComponent {
render() {
return <div style={{border: '1px solid black'}}>{this.props.text} : {this.props.inputValue} {Math.random()} <button onClick={() => {this.props.dismissClicked()}}>Click me</button> </div>
}
}
function TestFunctionalComponent () {
return <div style={{border: '1px solid black'}}>I always update as I am a functional component {Math.random()}</div>
}
const hell = () => {console.log('Logs hello')}
class RenderExample extends React.Component {
constructor (props) {
super(props)
this.state = {clicked: false, inputValue: 'inputValue'}
this.onClick = this.onClick.bind(this)
this.doSomething = this.doSomething.bind(this)
}
onClick () {
this.setState({clicked: !this.state.clicked})
}
doSomething () {
console.log('helllllo')
}
heee = () => {
console.log('heeeee')
}
render () {
return <div>
<button onClick={this.onClick}>
Update state (forces re-render) {this.state.clicked && 'clicked'}
</button>
<input onChange={(e) => this.setState({inputValue: e.target.value})} type="text" value={this.state.inputValue}/>
<br/>
<br/>
<TestFunctionalComponent />
<br/>
<TestPureComponent dismissClicked={() => hell} inputValue={this.state.inputValue} text="If you click the button this will re-render, if you change the input this will re-render"/>
<br/>
<TestPureComponent text="If you click the button this will NOT re-render, if you change the input this will re-render" dismissClicked={this.doSomething} inputValue={this.state.inputValue}/>
<br/>
<TestPureComponent text="If you click the button this will NOT re-render, if you change the input this will re-render" dismissClicked={this.heee} inputValue={this.state.inputValue}/>
<br/>
<TestPureComponent text="If you click the button this will NOT re-render, if you change the input this will re-render" dismissClicked={hell} inputValue={this.state.inputValue}/>
<br/>
<TestPureComponent text="If you click the button this will NOT re-render, if you change the input this will re-render" dismissClicked={hell} inputValue={this.state.inputValue}/>
<br/><br/>
<div> we will now add an inline object to each component and now they all update</div>
<TestPureComponent dismissClicked={() => hell} inlineOBJ={{hello: 'world'}} inputValue={this.state.inputValue} text="If you click the button this will re-render, if you change the input this will re-render"/>
<br/>
<TestPureComponent text="If you click the button this will re-render, if you change the input this will re-render" inlineOBJ={{hello: 'world'}} dismissClicked={this.doSomething} inputValue={this.state.inputValue}/>
<br/>
<TestPureComponent text="If you click the button this will re-render, if you change the input this will re-render" inlineOBJ={{hello: 'world'}} dismissClicked={this.heee} inputValue={this.state.inputValue}/>
<br/>
<TestPureComponent text="If you click the button this will re-render, if you change the input this will re-render" inlineOBJ={{hello: 'world'}} dismissClicked={hell} inputValue={this.state.inputValue}/>
<br/>
<TestPureComponent text="If you click the button this will re-render, if you change the input this will re-render" inlineOBJ={{hello: 'world'}} dismissClicked={hell} inputValue={this.state.inputValue}/>
</div>
}
}
ReactDOM.render(<RenderExample />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
我想看看是否有办法拥有一个 PureComponent,当有一个作为道具传入的 OBJECT 时,它不会总是更新。
【问题讨论】:
-
'当使用 PureComponents 时,您比功能组件具有优势,即在父更新时组件并不总是呈现。'它不是那样工作的。 PureComponent 和 Component 之间的区别在于,第一个没有
shouldComponentUpdate方法,而是在底层实现它并进行浅比较。我不完全理解你想要达到的目标。 -
试试
const TestFunctionalComponent = React.memo(function(){...),你会发现它永远不会更新。功能组件可以与container 一起使用,因此即使您传递了函数/对象,如果值没有改变,道具也永远不会改变引用。如果您的道具是计算对象,我建议使用容器和 React.memo。 -
@AndrzejZiółek 我想要的是有一个 PureComponent,当有一个作为道具传入的 OBJECT 时它不会总是更新(我会尝试重新表述问题)
-
所以不要在
render中内联构造对象 - 这样每次引用都会有所不同。 -
正如skyboyer 所建议的,不要在渲染中构造对象。如果您必须计算或合并值来创建道具,请使用容器和
React.memo。如果你渲染像onDelete={createDelete(id)}或onDelete={()=>anything}或item={{...dataItem,...editItem}}或item={{...item,updating}}这样的道具,你需要一个容器寻找 react-redux-connect 或 hooks 或 react-redux-hooks 以了解如何编写容器。
标签: javascript reactjs