React事件处理程序未按预期分配模式,评估为空

如何解决React事件处理程序未按预期分配模式,评估为空

我有一个看起来像这样的页面:

enter image description here

单击该行的编辑按钮时,该组件应该将所选实体设置为该行,并将其自身置于“编辑”模式。

但是,当在右上角显示一个框(此处称为toast的组件)时,第一次单击时该模式的评估结果为null

enter image description here

这是代码:

import React,{ Component } from 'react';

import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';
import { Button } from 'primereact/button';
import { Toast } from 'primereact/toast';

import 'primereact/resources/themes/luna-blue/theme.css';
import 'primereact/resources/primereact.min.css';
import 'primeicons/primeicons.css';

const modes =
{
    VIEW:   'VIEW',ADD:    'ADD',EDIT:   'EDIT',REMOVE: 'REMOVE'
}

class TestManager extends Component
{
    constructor()
    {
        super();

        let persons = [
            {
                "id": 3,"zipCode": "","cityName": "","streetName": "","houseNbr": "","firstName": "Ahmed","lastName": "Al-Thiab","gender": "MALE",},{
                "id": 4,"firstName": "Stefan","lastName": "Antalovics",{
                "id": 20,"firstName": "Christian","lastName": "Attina",{
                "id": 15,"firstName": "Filmon","lastName": "Berhane",{
                "id": 2,"zipCode": "64895","cityName": "Darmstadt","firstName": "Johannes","lastName": "Loczewski",{
                "id": 1,"zipCode": "22880","cityName": "Wedel","streetName": "Rosengarten","houseNbr": "6","firstName": "Karsten","lastName": "Wutzke",}
        ]
        
        this.state = {entities: persons,selectedEntity: null,mode: null};
        
        this.onRowEdit = this.onRowEdit.bind(this);
        this.onRowRemove = this.onRowRemove.bind(this);
        
        this.actions = this.actions.bind(this);
    }
    
    render()
    {
        var header = "Person Manager (" + this.state.entities.length + ")"

        return (
            <div style={{ maxWidth: 1000,marginLeft: "auto",marginRight: "auto",marginTop: 10,marginBottom: 10 }}>
                
                <Toast ref={(el) => this.toast = el} />
                
                <DataTable value={this.state.entities}
                           header={header}
                           dataKey="id"
                           selection={this.state.selectedEntity}
                           selectionMode="single"
                           sortField='lastName'
                           sortOrder={1}
                           resizableColumns
                           columnResizeMode="fit"
                           className="p-datatable-striped">
                    <Column field="id" header='ID' sortable style={{width:'7.5%'}} />
                    <Column field="gender" header='Sal.' body={this.salutation} sortable style={{width:'10%'}} />
                    <Column field='lastName' header='Last Name' sortable style={{width:'15%'}} />
                    <Column field='firstName' header='First Name' sortable style={{width:'15%'}} />
                    <Column field='streetName' header='Street' body={this.street} sortable style={{width:'20%'}} />
                    <Column field='zipCode' header='ZIP' sortable style={{width:'10%'}} />
                    <Column field='cityName' header='City' sortable style={{width:'10%'}} />
                    <Column field="actions" body={this.actions} style={{width:'12.5%'}} />
                </DataTable>
            </div>
        );
    }

    actions(rowData)
    {
        return (
            <>
                <div style={{textAlign: "center"}}>
                    <Button icon="pi pi-pencil"
                            tooltip="Edit"
                            onClick={() => this.onRowEdit(rowData)}
                            className="p-button-sm p-button-raised p-button-rounded p-button-outlined" />
                    <Button icon="pi pi-trash"
                            tooltip="Remove"
                            className="p-button-sm p-button-raised p-button-rounded p-button-outlined"
                            onClick={() => this.onRowRemove(rowData)}
                            style={{marginLeft: 5}} />
                </div>
            </>
        );
    }

    onRowEdit(rowData)
    {
        this.setState({selectedEntity: rowData});
        this.setState({mode: modes.EDIT});

        console.log("Last name: " + rowData.lastName);
        console.log("Mode: " + this.state.mode);

        this.toast.show({ severity: 'info',summary: 'Editing Person',detail: 'Name: ' + rowData.lastName + "," + this.state.mode,life: 3000 });
    }

    onRowRemove(rowData)
    {
        this.setState({selectedEntity: rowData});
        this.setState({mode: modes.REMOVE});

        this.toast.show({ severity: 'info',summary: 'Removing Person',life: 3000 });
    }

    salutation(rowData)
    {
        var gender = rowData['gender'];

        if ( gender )
        {
            switch( gender )
            {
                case "MALE":
                    return "Mr";
                
                case "FEMALE":
                    return "Mrs";
                
                default:
                    return "Error";
            }
        }

        return null;
    }

    street(rowData)
    {
        var streetName = rowData['streetName'];
        var houseNumber = rowData['houseNbr'];

        return houseNumber ? streetName + " " + houseNumber : streetName;
    }
}

export default TestManager;

问题

这是怎么了?

据此

Does React keep the order for state updates?

方法回调(也称为事件处理程序,更新模式)应该没有任何问题

onRowEdit(rowData)
{
    this.setState({selectedEntity: rowData});
    this.setState({mode: modes.EDIT});

    console.log("Last name: " + rowData.lastName);
    console.log("Mode: " + this.state.mode);

    this.toast.show({ severity: 'info',life: 3000 });
}

this.state.mode始终是null。在随后的点击中,无论哪一行,都将显示正确的模式。

为什么?

我该如何解决?

顺便说一句:this.state.selectedEntity在使用吐司的行上也是null

我很难理解这一点。 ->自学

解决方法

setState是异步的。您不能期望状态已经改变。

尝试一下:

this.setState({mode: modes.EDIT},() => {
  console.log("Mode: " + this.state.mode);
});
,

在下一次渲染之前,状态更新不会(有必要)反映在this.state中。

来自the docs

setState()并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用setState()之后立即读取this.state可能是一个陷阱。而是使用componentDidUpdate或setState回调

您已经知道该模式,因此可以通过modes.EDIT而不是this.state.mode

this.toast.show({ detail: "..." + modes.EDIT,life: 3000 });

或使用setState的回调形式,以确保在调用后续的Toast代码之前状态已更新:

this.setState({mode: modes.EDIT},() => this.toast.show( ... ))

注意:因为console.log异步运行,所以您的console.log调用可能会显示更新后的值。 (在您调用它的时间与它在控制台中显示的时间之间,状态可能已更改。)

,

这是一个公平的问题,但是setState是异步的。因此,要么在其中使用回调函数,要么使用Promise在另一个setState之后执行一些setState

this.setState( (mode) => mode : modes.EDIT)

Promise.all(#First Async).then(#Second Async)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res