J'essaie de refactoriser une classe dans un composant sans état en utilisant des crochets React
.
Le composant lui-même est très simple et je ne vois pas où je fais une erreur, car il s'agit presque d'un copier-coller des documents React.
Le composant affiche une fenêtre contextuelle lorsque l'utilisateur clique sur un bouton (le bouton est transmis via les accessoires à mon composant). J'utilise TypeScript
.
J'ai commenté la ligne qui ne fait pas ce que je veux dans la version hooks
Voici ma classe d'origine:
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>
)
}
}
Ici se trouve le React hooks
version:
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>
)
}
Tout comme setState, le comportement de mise à jour de l'état à l'aide de crochets nécessitera également un nouveau rendu et une mise à jour et, par conséquent, le changement ne sera pas immédiatement visible. Si toutefois vous essayez de consigner l'état en dehors de la méthode handleVisibleChange, vous verrez l'état de mise à jour
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>
)
}
Toute action que vous devez entreprendre en fonction de la mise à jour de l'état peut être effectuée à l'aide du crochet useEffect
comme
useEffect(() => {
// take action when isVisible Changed
}, [isVisible])