2016-08-19 83 views
3

我有這樣高階組件總是重新渲染忽略shouldComponentUpdate

// higherOrderComponent.js 
const HigherOrderComponent = Component => class extends React.Component { 
    shouldComponentUpdate (nextProps, nextState) { 
    return false 
    } 

    render() { 
    return <Component {...this.props} /> 
    } 
} 

export default HigherOrderComponent 

// myComponent.js 
import HigherOrderComponent from './higherOrderComponent' 

class MyComponent extends React.Component { 
    render() { 
    return <div>my component</div> 
    } 
} 

export default HigherOrderComponent(MyComponent) 

// parentComponent.js 
import MyComponent from './myComponent' 

class ParentComponent extends React.Component { 
    render() { 
    return <MyComponent /> 
    } 
} 

高階組件我明確地返回false,但分量總是得到重新呈現。任何想法爲什麼?我最終希望在各個組件之間共享「shouldComponentUpdate」。如果高階組件不起作用,我該如何做到這一點?

+0

總要得到重新呈現什麼時候? –

+0

你好,我根據你的組件編寫了一些代碼,發現你確實是對的。讓我看看我們該如何解決這個問題。 –

回答

0

這是關於反應組分的生命週期。當一個組件被初始化時,它不會檢查shouldComponentUpdate。 ShouldComponentUpdate只會在state/props CHANGED時被調用。

FYI生命週期方法調用,以便:

當組件被初始化: getDefaultProps getInitialStage componentWillMount 渲染 componentDidMount

當組件已狀態改變: shouldComponentUpdate componentWillUpdate render componentDidUpdate

當組件道具變化: componentWillReceiveProps shouldComponentUpdate componentWillUpdate 渲染 componentDidUpdate

當一個組件卸載: componentWillUnmount

+0

這是不正確的。根據這裏的文檔,https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate「如果shouldComponentUpdate返回false,那麼render()將被完全跳過,直到下一個狀態改變」 – manni

+0

@manni文檔說:「在接收到新的道具或狀態時,在渲染之前調用。這種方法不用於初始渲染或使用forceUpdate。」當組件初始化時,shouldComponentUpdate不用於渲染前的檢查。 – Vivian

+0

@manni我創建了一個示例。 https://jsfiddle.net/viviancpy/3228rctx/1/您可以打開Chrome控制檯(F12)並觀察打印的日誌。組件初始化短語中沒有爲ShouldComponentUpdate打印任何內容。 – Vivian

2

因爲你還沒有規定如何根據我所做的問題調用您的高階組件猜猜你會如何使用它。

我的回答是基於你調用像

var MyHigherOrderFn = (HigherOrderComponent(Baar)); 

您的高階函數的假設。如果有些你怎麼可以調用您的高階函數類似下面爲returnrender,你可以迴避的問題。

<HigherOrderComponent prop1="Hello" child="Child" /> 

因爲我不;知道如何在上面的方式調用你的函數(我不知道它甚至有可能),我創建HigherOrderComponent2不同的語法格式可以調用一樣,這又符合shouldComponentUpdate

<Parent prop1="val1"> 
    <Child> 
</Parent> 

import React, {PropTypes} from 'react'; 


/*This is simeple child component*/ 
class Baar extends React.Component {  
    render() { 
    return (<div>{this.props.name}</div>); 
    } 
} 


/*This is your higher order component*/ 
const HigherOrderComponent = Component => class extends React.Component { 
    shouldComponentUpdate (nextProps, nextState) { 
    return false; 
    } 

    render() { 
    return <Component {...this.props} /> 
    } 
} 

/*This is another way to write higher order component*/ 
class HigherOrderComponent2 extends React.Component { 
    constructor(props) { 
    super(props); 
    } 

    shouldComponentUpdate (nextProps, nextState) { 
    return false; 
    } 

    render(){ 

    let child = this.props.children && React.cloneElement(this.props.children, 
     {...this.props} 
    ); 

    return <div>{child}</div> 
    } 
} 



/*Problem that you are facing how you invoke your Higher Order Compoent*/ 
export default class Foo extends React.Component { 
    constructor(props) { 
    super(props); 
    this.onHandleClick = this.onHandleClick.bind(this); 
    this.state={ 
     name: 'Praveen Prasad' 
    } 
    } 

    onHandleClick(){ 
    this.setState({ 
     name:Math.random() 
    }); 
    } 

    render() { 
    {'This is how you might be invoking you higher order component, at this time react render doesnt know it already exists in DOM or not'} 
    {'this component will always re-render, irrespective of values in shouldComponentUpdate'} 
    var Baaz = (HigherOrderComponent(Baar)); 
    return (<div> 
     <button onClick={this.onHandleClick}>Update Name</button> 
     <Baaz name={this.state.name} /> 

     {'This is another way to invoke higher order Component , and this will respect shouldComponentUpdate'} 
     <HigherOrderComponent2 name={this.state.name}> 
      <Baar /> 
     </HigherOrderComponent2> 
    </div>); 
    } 
} 
+0

我真的不想爲更高階的組件創建另一個更高階的組件來使其工作。 – manni

+0

我不是說要創建另一個HOF,但我說的是你如何使用它。 –

+0

代碼中的問題是您可能會如何使用它。 –

1

我已經修改了你的代碼來創建一個片段,並如預期運作,MyComponent.render只調用一次當shouldComponentUpdate返回false

我的猜測是,你使用MyComponent的解包版本而不是包裝的版本。也許你的構建環境有問題?

// higherOrderComponent.js 
 
const HigherOrderComponent = Component => class extends React.Component { 
 
    shouldComponentUpdate (nextProps, nextState) { 
 
    return false; 
 
    } 
 

 
    render() { 
 
    return <Component {...this.props} /> 
 
    } 
 
} 
 

 
class MyComponent extends React.Component { 
 
    render() { 
 
    \t console.log('render'); 
 
    return <div>my component</div> 
 
    } 
 
} 
 

 
const MyComponentHOC = HigherOrderComponent(MyComponent); 
 

 
class ParentComponent extends React.Component { 
 
    render() { 
 
    return <MyComponentHOC /> 
 
    } 
 
} 
 

 
ReactDOM.render(<ParentComponent/>, document.getElementById('container')); 
 
ReactDOM.render(<ParentComponent/>, document.getElementById('container'));
<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> 
 

 

 
<div id="container"></div>

1

您將需要使用不同類型的HOC模式稱爲繼承反轉的訪問生命週期方法。由於您覆蓋了shouldComponentUpdate,因此您不要致電super,但需要在子類化組件render方法內調用super.render()

嘗試......

const HigherOrderComponent =() => WrappedComponent => 
    class ShouldNotUpdate extends WrappedComponent { 
    shouldComponentUpdate(nextProps) { 
     return false 
    } 
    render() { 
     return super.render() 
    } 
    } 

它的使用討好所以你可以在將來像你註釋類好習慣......

@HigherOrderComponent 
class MyClass extends React.Component { 
    render() { 
    return <div>something</div> 
    } 
} 

// or without annotations.. 

const MyNewClass = HigherOrderComponent()(MyClass) 
相關問題