Я пытаюсь преобразовать класс в компонент без сохранения состояния с помощью ловушек React.
Сам компонент очень прост, и я не понимаю, где я делаю ошибку, так как это почти копипаст из документации по реакции.
Компонент показывает всплывающее окно, когда пользователь нажимает кнопку (кнопка передается через реквизиты моему компоненту). Пользуюсь typescript.
Я прокомментировал строку, которая не выполняет то, что я хочу, в версии для hooks
Вот мой оригинальный класс:
export interface NodeMenuProps extends PropsNodeButton {
title?: string
content?: JSX.Element
button?: JSX.Element
}
export interface NodeMenuState {
visible: boolean
}
export class NodeMenu extends React.Component<NodeMenuProps, NodeMenuState> {
state = {
visible: false
}
hide = () => {
this.setState({
visible: false
})
}
handleVisibleChange = (visible: boolean) => {
this.setState({ visible })
}
render() {
return (
<div className = {this.props.className}>
<div className = {styles.requestNodeMenuIcon}>
<Popover
content = {this.props.content}
title = {this.props.title}
trigger = "click"
placement = "bottom"
visible = {this.state.visible}
onVisibleChange = {this.handleVisibleChange}
>
{this.props.button}
</Popover>
</div>
</div>
)
}
}
Вот версия для React hooks:
export interface NodeMenuProps extends PropsNodeButton {
title?: string
content?: JSX.Element
button?: JSX.Element
}
export const NodeMenu: React.SFC<NodeMenuProps> = props => {
const [isVisible, setIsVisible] = useState(false)
const hide = () => {
setIsVisible(false)
}
const handleVisibleChange = (visible: boolean) => {
console.info(visible) // visible is `true` when user clicks. It works
setIsVisible(visible) // This does not set isVisible to `true`.
console.info(isVisible) // is always `false` despite `visible` being true.
}
return (
<div className = {props.className}>
<div className = {styles.requestNodeMenuIcon}>
<Popover
content = {props.content}
title = {props.title}
trigger = "click"
placement = "bottom"
visible = {isVisible}
onVisibleChange = {handleVisibleChange}
>
{props.button}
</Popover>
</div>
</div>
)
}
Вместо этого setVisible запускает повторный рендеринг. Когда мы снова выполним рендеринг, для него будет установлено новое значение.
У меня такая же проблема, но мой jsx обновляется, а значение константы в моей функции нет :( @ DJ2





Как и в случае с setState, поведение обновления состояния с использованием хуков также потребует повторного рендеринга и обновления, и, следовательно, изменение не будет сразу видно. Однако если вы попытаетесь записать состояние вне метода handleVisibleChange, вы увидите состояние обновления
export const NodeMenu: React.SFC<NodeMenuProps> = props => {
const [isVisible, setIsVisible] = useState(false)
const hide = () => {
setIsVisible(false)
}
const handleVisibleChange = (visible: boolean) => {
console.info(visible) // visible is `true` when user clicks. It works
setIsVisible(visible) // This does not set isVisible to `true`.
}
console.info({ isVisible });
return (
<div className = {props.className}>
<div className = {styles.requestNodeMenuIcon}>
<Popover
content = {props.content}
title = {props.title}
trigger = "click"
placement = "bottom"
visible = {isVisible}
onVisibleChange = {handleVisibleChange}
>
{props.button}
</Popover>
</div>
</div>
)
}
Любое действие, которое вам нужно предпринять в зависимости от того, было ли обновлено состояние, можно выполнить с помощью ловушки useEffect, например
useEffect(() => {
// take action when isVisible Changed
}, [isVisible])
Спасибо, Шубхам, теперь я вижу, что значение обновляется. Однако, поскольку isVisible становится true при повторном рендеринге, я не понимаю, почему всплывающее окно не отображается. Я прочитал документацию об useEffect, но не понимаю, почему мне нужно использовать это для отображения всплывающего окна, если isVisible действительно меняется на true?
вам не нужно использовать useEffect. Это была просто дополнительная информация
@ShubhamKhatri означает ли это, что обработчик изменений также должен быть перемещен в ловушку useEffect?
Я тоже столкнулся с подобной проблемой, но не нашел решения.
visible- это константа, определенная в вашем компоненте. Невозможно, чтобы вызов функции любой мог изменить его значение.