2016-11-27 2 views
0

Мне любопытно, почему Реагировать обновления Младенец компонентов в этом случае:Почему React вызывает метод рендеринга неизмененного компонента?

function Inner(props) { 
    console.log("Render Inner"); 
    return <div>Inner</div>; 
} 

export class Outer extends React.Component { 

    constructor(props) { 
    super(props); 
    this.state = { 
     active: false 
    }; 
    this.onClick = this.rawOnClick.bind(this); 
    } 

    render() { 
    console.log("Render Outer"); 
    return <div onClick={this.onClick} style={{ backgroundColor: this.state.active ? 'red': 'blue'}}><Inner/></div>; 
    } 

    rawOnClick(event) { 
    this.setState({ active: !this.state.active }); 
    } 
} 


ReactDOM.render(<Outer/>, document.getElementById('app')); 

Когда компонент Outer нажата, метод визуализации внутренней и внешней называются. Поскольку компоненты должны быть «чистыми», нет необходимости называть метод визуализации Inner, есть ли? Я могу даже сделать это таким образом, если я переписать мой код немного:

export function Inner(props) { 
    console.log("Render Inner"); 
    return <div>Inner</div>; 
} 

export class Outer2 extends React.Component { 

    constructor(props) { 
    super(props); 
    this.state = { 
     active: false 
    }; 
    this.onClick = this.rawOnClick.bind(this); 
    } 

    render() { 
    console.log("Render Outer"); 
    return <div onClick={this.onClick} style={{ backgroundColor: this.state.active ? 'red': 'blue'}}>{this.props.children}</div>; 
    } 

    rawOnClick(event) { 
    this.setState({ active: !this.state.active }); 
    } 
} 

ReactDOM.render(<Outer2><Inner /></Outer2>, document.getElementById('app')); 

Теперь только метод визуализации «Outer2» вызывается, когда я нажимаю компонент. Это намеренно? Является ли это оптимизацией миссии или мне не хватает чего-то важного.

Спасибо.

Peter

+0

После проверки дополнительной документации я нашел то, что хотел: мне нужно: this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind (this); 'в конструкторе это поведение, которое я ожидаю. Мне все еще кажется странным, что документация говорит об этом «чистом» рендеринге все время, а затем игнорирует его (особенно в «функциональных» компонентах). Но я могу справиться. Спасибо всем. – ptriller

+0

Извините, мне нужен только «React.PureComponent» в качестве базового класса, и у меня есть поведение, которое я хочу. – ptriller

ответ

1

Это поведение по умолчанию React. Вы должны переопределить shouldComponentUpdate() в свой Внутренний компонент, чтобы вернуть true или false, чтобы определить, нужно ли снова вызывать его собственный render(). Это определение обычно делается на основе различий, если таковые имеются, между текущим и следующим набором реквизита и состояния.

В вашем примере, где ваш Внутренний компонент всегда возвращает одно и то же и на него не влияют изменения в реквизитах или состоянии, вы можете просто вернуть false.

shouldComponentUpdate(nextProps, nextState) { 
    return false; 
}; 

(Примечание, вы должны преобразовать Внутренне из вашего лица без функции класса ES6 для того, чтобы использовать этот метод жизненного цикла.)

Узнайте больше на официальных документах - https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate

+0

Я был просто смущен поведением по умолчанию, когда реквизиты не изменяются, а просто устанавливаются в одни и те же значения.В документации говорится: «Поведение по умолчанию заключается в повторном рендеринге при каждом изменении состояния ...», но поскольку состояние не изменяется, когда все свойства просто установлены на одни и те же значения, я предполагал, что он не будет рендерить. – ptriller

1

В в первом случае состояние внешнего компонента изменяется при запуске события щелчка. Из-за изменения состояния запускается метод рендеринга. Поскольку внутренний компонент находится внутри метода рендеринга, он также получает re rendered и вызывается метод визуализации внутреннего компонента.

Поскольку во втором случае внутренний компонент не находится внутри метода визуализации внешнего компонента, он не будет отображаться, даже если изменяется состояние внешнего компонента.

Ваш второй случай будет работать только в том случае, если вы не передадите что-то из состояния внешнего компонента во внутренний компонент в качестве опоры. Как только вы это сделаете, изменение ключа состояния, которое передается в качестве опоры для внутреннего компонента, снова вызовет метод визуализации внутреннего компонента

Если вы хотите передать что-то из состояния внешнего компонента во внутреннее компонент в качестве опоры и избегать ненужных вызовов визуализации внутреннего компонента, вам придется перейти от внутреннего компонента без состояния к внутреннему компоненту и пользователю, основанному на классе, для использования метода жизненного цикла shouldComponentUpdate, чтобы ограничить метод визуализации внутреннего компонента

+0

Спасибо. Я понимаю, что это не то, чего я ожидал, потому что React не создает новый экземпляр компонента Inner, поэтому он мог проверить, что он не изменил никаких свойств и не пропустил рендеринг, потому что это чистый контракт. Но если так оно и есть, то так оно и есть. – ptriller

Смежные вопросы