【问题标题】:React Hooks - Modified state not reflecting immediatelyReact Hooks - 修改后的状态没有立即反映
【发布时间】:2019-04-24 23:31:32
【问题描述】:

我正在尝试使用 React 挂钩将一个类重构为无状态组件。

组件本身非常简单,我看不出哪里出错了,因为它几乎是来自 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>
  )
}

【问题讨论】:

  • visible 是您的组件中定义的常量。调用 any 函数不可能改变它的值。
  • 相反,setVisible 会触发重新渲染。当我们再次渲染时,它会被设置为一个新的值。
  • 我面临同样的问题,但我的 jsx 正在更新,但我的函数中的常量值不是:( @DJ2

标签: reactjs typescript react-hooks


【解决方案1】:

很像 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])

【讨论】:

  • 感谢 Shubham,我现在可以看到值正在更新。但是,由于isVisible 在重新渲染时变为true,我不明白为什么弹出框没有出现。我阅读了有关 useEffect 的文档,但我不明白为什么我需要使用它来显示弹出窗口,因为 isVisible 确实更改为 true?
  • 你不需要使用useEffect。这只是一个附加信息
  • @ShubhamKhatri 这是否意味着更改处理程序也应该移动到 useEffect 挂钩内?
  • 我也面临类似的问题,但没有找到解决方案。
猜你喜欢
  • 2020-05-11
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-28
  • 2020-05-12
相关资源
最近更新 更多