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.log(visible) // visible is `true` when user clicks. It works
setIsVisible(visible) // This does not set isVisible to `true`.
console.log(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>
)
}
SetStateと同様に、フックを使用した状態更新動作でも再レンダリングと更新が必要になるため、変更はすぐには表示されません。ただし、handleVisibleChangeメソッドの外部で状態をログに記録しようとすると、更新状態が表示されます
export const NodeMenu: React.SFC<NodeMenuProps> = props => {
const [isVisible, setIsVisible] = useState(false)
const hide = () => {
setIsVisible(false)
}
const handleVisibleChange = (visible: boolean) => {
console.log(visible) // visible is `true` when user clicks. It works
setIsVisible(visible) // This does not set isVisible to `true`.
}
console.log({ 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])