React Hooks - 修改后的状态不会立即反映 [英] React Hooks - Modified state not reflecting immediately

查看:23
本文介绍了React Hooks - 修改后的状态不会立即反映的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 React 钩子将类重构为无状态组件.

组件本身非常简单,我看不出我哪里出错了,因为它几乎是从 react 文档中复制粘贴过来的.

当用户单击按钮时,组件会显示一个弹出窗口(按钮通过道具传递给我的组件).我正在使用 typescript.

我评论了在 hooks 版本中没有做我想做的事情

这是我原来的课程:

export interface NodeMenuProps extends PropsNodeButton {标题?:字符串内容?:JSX.Element按钮?:JSX.Element}导出接口 NodeMenuState {可见:布尔值}导出类 NodeMenu 扩展了 React.Component{状态 = {可见:假}隐藏 = () =>{this.setState({可见:假})}handleVisibleChange = (visible: boolean) =>{this.setState({可见})}使成为() {返回 (

<div className={styles.requestNodeMenuIcon}><弹窗内容={this.props.content}标题={this.props.title}触发器=点击"位置=底部"可见={this.state.visible}onVisibleChange={this.handleVisibleChange}>{this.props.button}</弹出框>

)}}

这是 React hooks 版本:

export interface NodeMenuProps extends PropsNodeButton {标题?:字符串内容?:JSX.Element按钮?:JSX.Element}导出 const NodeMenu:React.SFC= 道具 =>{const [isVisible, setIsVisible] = useState(false)const 隐藏 = () =>{设置可见(假)}const handleVisibleChange = (visible: boolean) =>{console.log(visible)//当用户点击时可见是 `true`.有用setIsVisible(visible)//这不会将 isVisible 设置为 `true`.console.log(isVisible)//尽管 `visible` 为真,但始终为 `false`.}返回 (<div className={props.className}><div className={styles.requestNodeMenuIcon}><弹窗内容={道具.内容}标题={道具.标题}触发器=点击"位置=底部"可见={isVisible}onVisibleChange={handleVisibleChange}>{道具.按钮}</弹出框>

)}

解决方案

很像 setState,使用钩子的状态更新行为也需要重新渲染和更新,因此更改不会立即可见.但是,如果您尝试在 handleVisibleChange 方法之外记录状态,您将看到更新状态

export const NodeMenu: React.SFC= 道具 =>{const [isVisible, setIsVisible] = useState(false)const 隐藏 = () =>{设置可见(假)}const handleVisibleChange = (visible: boolean) =>{console.log(visible)//当用户点击时可见是 `true`.有用setIsVisible(visible)//这不会将 isVisible 设置为 `true`.}console.log({ isVisible });返回 (<div className={props.className}><div className={styles.requestNodeMenuIcon}><弹窗内容={道具.内容}标题={道具.标题}触发器=点击"位置=底部"可见={isVisible}onVisibleChange={handleVisibleChange}>{道具.按钮}</弹出框>

)}

您需要根据状态是否更新而采取的任何操作都可以使用 useEffect 钩子来完成,例如

useEffect(() => {//当 isVisible 改变时采取行动}, [isVisible])

I'm trying to refactor a class into a stateless component using React hooks.

The component itself is very simple and I don't see where I'm making a mistake, as it's almost a copy paste from the react docs.

The component is showing a popup when the user clicks on a button (button is passed through props to my component). I'm using typescript.

I commented the line that fails to do what I want in the hooks version

Here's my original class:

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>
    )
  }
}

Here's the 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>
  )
}

解决方案

Much like setState, the state update behaviour using hooks will also require a re-render and update and hence the change will not be immedialtely visible. If however you try to log state outside of the handleVisibleChange method, you will see the update state

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>
  )
}

Any action that you need to take on the basis of whether the state was update can be done using the useEffect hook like

useEffect(() => {
   // take action when isVisible Changed
}, [isVisible])

这篇关于React Hooks - 修改后的状态不会立即反映的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆