反应状态没有更新

Posted

技术标签:

【中文标题】反应状态没有更新【英文标题】:React state does not get updated 【发布时间】:2020-05-19 18:31:56 【问题描述】:

我知道已经有很多关于这个话题的问题被问到了,但感觉每个问题都不同,我找不到与我的问题足够接近的问题。

我有一个带有可拖动ItemComponents 的网格。选择后,会显示其他操作图标 (ItemActionIcon)。单击其中一个操作后,我非常希望取消选择组件(并有效地隐藏操作图标)。

所以在第 77 行 <div onClick=() => this.setState(selected: false) key=index> 我正在尝试将 selected 的状态更新为 false。在文件中提到的所有其他情况下,它已经可以正常工作了。但在这种情况下不是。当我单击该图标时,我可以使用调试器(或尝试使用 console.log)看到 onClick 操作按预期触发,ItemComponent 甚至再次调用 render 方法,但this.state.selected 仍设置为true

import React, Component from "react";
import Draggable, DraggableBounds from "react-draggable";
import ItemComponentAction from "./ItemComponentAction";
import ItemActionIcon from "./ItemActionIcon";

export interface Position 
    x: number;
    y: number;


export interface ItemComponentProps 
    gridSquareSize: number;
    canvasBounds: DraggableBounds;
    margin: number;
    position: Position;


interface ItemComponentState 
    gridSquareSize: number;
    canvasBounds: DraggableBounds;
    margin: number;
    selected: boolean;


export default abstract class ItemComponent extends Component<ItemComponentProps> 

    protected abstract readonly icon: string;
    protected abstract readonly actions: ItemComponentAction[];

    state: ItemComponentState;

    protected constructor(props: ItemComponentProps) 
        super(props);
        this.state = 
            gridSquareSize: props.gridSquareSize,
            canvasBounds: props.canvasBounds,
            margin: props.margin,
            selected: false
        ;
    

    render() 
        return (
            <Draggable grid=[this.state.gridSquareSize / 2, this.state.gridSquareSize / 2]
                       defaultPosition=
                           x: this.state.margin + this.props.position.x * this.state.gridSquareSize,
                           y: this.state.margin + this.props.position.y * this.state.gridSquareSize
                       
                       handle=".handle"
                       bounds=this.state.canvasBounds
                       onDrag=() => this.setState(selected: false)
            >
                <div tabIndex=0
                     className="handle"
                     onClick=() => this.setState(selected: true)
                     onBlur=() => this.setState(selected: false)
                     style=
                        position: 'absolute',
                        backgroundColor: 'red',
                        width: this.state.gridSquareSize,
                        height: this.state.gridSquareSize,
                        cursor: "move"
                     
                >
                    this.icon

                    
                        !this.state.selected || !this.actions.length
                           ? null
                           : (
                                <div style=
                                    position: 'absolute',
                                    bottom: "0"
                                >
                                    
                                        this.actions.map((action, index) => (
                                            <div onClick=() => this.setState(selected: false) key=index>
                                                <ItemActionIcon ...action/>
                                            </div>
                                        ))
                                    
                                </div>
                            )
                    
                </div>
            </Draggable>
        );
    

那么有什么关系呢?

【问题讨论】:

似乎您在父 div 中有一个 onclick 处理程序,将 selected 设置为 false?如果点击内层div,外层div的onclick函数不也会运行吗...? 不...实际上不是...父母的 onClick 没有被触发...但无论如何我都会提取整个内容。也许这会触发这件事 你做了什么来验证父onClick是否被触发? 我不确定我是否可以信任调试器(编译 TS 后断点通常会出现在错误的位置),所以我只是添加了 console.log() 很可能 onClick 实际上被触发了,而您只是没有看到它或没有明显地记录它。为了进一步验证这一点,您可以尝试将代码与问题中的示例相同,并在内部 div onClick 事件上执行 event.stopPropagation() 【参考方案1】:

组件的外部&lt;div&gt; 有自己的onClick 处理程序,它将您的状态值设置回false。尝试在内部 onClick 处理的事件上使用 stopPropagation()。这将阻止事件传播到外部父级&lt;div&gt;,并且只有内部onClick 处理程序在被单击时才会执行。


  !this.state.selected || !this.actions.length ? null : (
    <div
      style=
        position: "absolute",
        bottom: "0"
      
    >
      this.actions.map((action, index) => (
        <div
          onClick=e => 
            e.stopPropagation();
            this.setState( selected: false );
          
          key=index
        >
          <ItemActionIcon ...action />
        </div>
      ))
    </div>
  );

【讨论】:

以上是关于反应状态没有更新的主要内容,如果未能解决你的问题,请参考以下文章

反应状态没有在 SetInterval 方法中正确更新

第一次点击时反应状态值没有更新

使用 componentDidUpdate 在反应中更新状态

在反应类组件中,为啥在按钮单击的第一个实例中状态没有改变?但在第二种情况下,它会更新吗?

数组状态更新后反应不重新渲染

在反应中更新三元运算符内的状态