В моем коде есть компонент, который принимает оба реквизита и имеет свое собственное внутреннее состояние.
Компонент должен перерисовываться ТОЛЬКО при смене реквизита. Изменения состояния НЕ должны вызывать повторное рендеринг.
Это поведение может быть реализовано с помощью компонента на основе классов и пользовательской функции shouldComponentUpdate
.
Однако это будет первый компонент на основе классов в кодовой базе. Все сделано с функциональными компонентами и крючками. Поэтому я хотел бы знать, можно ли кодировать желаемую функциональность с помощью функциональных компонентов.
После нескольких ответов, которые не подошли к реальной проблеме, я думаю, что мне нужно переформулировать свой вопрос. Вот минимальный пример с двумя компонентами:
- Внутренний получает опору и имеет состояние. Это рассматриваемый компонент. Он не должен повторно отображаться после изменения состояния. Изменения реквизита должны вызвать повторное рендеринг.
- Внешняя оболочка - это внутренняя оболочка. Это не имеет никакого смысла в рамках этого вопроса и предназначено только для того, чтобы поддержать Inner и смоделировать его изменения.
Чтобы продемонстрировать желаемую функциональность, я реализовал Inner с компонентом на основе классов. Живая версия этого кода может быть найдена на codeandbox . Как перенести его в функциональный компонент:
Inner.tsx
:
import React, { Component } from 'react'
interface InnerProps{outerNum:number}
interface InnerState{innerNum:number}
export default class Inner extends Component<InnerProps, InnerState> {
state = {innerNum:0};
shouldComponentUpdate(nextProps:InnerProps, nextState:InnerState){
return this.props != nextProps;
}
render() {
return (
<button onClick={()=>{
this.setState({innerNum: Math.floor(Math.random()*10)})
}}>
{`${this.props.outerNum}, ${this.state.innerNum}`}
</button>
)
}
}
Outer.tsx:
import React, { useState } from "react";
import Inner from "./Inner";
export default function Outer() {
const [outerState, setOuterState] = useState(1);
return (
<>
<button
onClick={() => {
setOuterState(Math.floor(Math.random() * 10));
}}
>
change outer state
</button>
<Inner outerNum={outerState}></Inner>
</>
);
}
В официальных документах сказано , чтобы обернуть компонент в React.memo
. Но это, кажется, не работает для предотвращения повторных обращений при смене состояния. Это относится только к изменениям реквизита.
Я пытался заставить React.memo
работать. Вы можете увидеть версию кода с внешними и внутренними функциональными компонентами здесь .
Смежные вопросы:
Как использовать shouldComponentUpdate с React Hooks? : Этот вопрос касается только изменений проп. Принятый ответ рекомендует использовать React.memo
shouldComponentUpdate в функциональных компонентах : Этот вопрос предшествует функциональным компонентам с состоянием. Принятый ответ объясняет, почему функциональным компонентам не нужно shouldComponentUpdate
, поскольку они не сохраняют состояние.