#独家
React子组件回调父组件状态数据问题?

2023-04-15 0 2,293

子组件如下:

import { Button, Select } from "antd";
import { useState } from "react";

const BatchOperation = (props: BatchOperationProps) => {

    const { options = [], onOk: globalOk, onChange } = props;

    const [selectedOption, setSelectedOption] = useState<OperationType>(options[0]);

    const { onOk = globalOk } = selectedOption;

    return <div style={{ padding: 6, border: '1px solid #d8d8d8', display: 'inline-flex', gap: 6 }}>
        <div>
            <Select
                options={options} defaultValue={selectedOption?.value}
                dropdownMatchSelectWidth={false} showSearch={false}
                style={{ width: 'max-content', maxWidth: 160 }}
                onChange={selValue => {
                    const selected = options.find(({ value }) => value === selValue);
                    if (!!selected) {
                        setSelectedOption(selected);
                        onChange?.(selValue);
                    } else {
                        throw '选项错误';
                    }
                }}></Select>
        </div>
        <Button type="primary" onClick={() => {
            onOk?.();
        }}>Button</Button>
    </div>;
};

export default BatchOperation;

export interface OperationType {
    value: string;
    label: string;
    onOk?: () => Promise<void>;
}

interface BatchOperationProps {
    options: OperationType[]
    onOk?: () => Promise<void>
    onChange?: (value: string) => void
}

父组件如下:

import { ProColumns, ProTable } from '@ant-design/pro-components';
import { useState } from 'react';
import BatchOperation from './Batch';
import './index.css';

const Test = () => {

    const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);

    const columns: ProColumns<any>[] = [
        {
            title: '员工姓名',
            dataIndex: 'name'
        },
        {
            title: '员工工号',
            dataIndex: 'code'
        }
    ];

    const onOk = async () => {
        console.info('ok: ', selectedRowKeys); // 3
    };

    return (
        <ProTable
            bordered rowKey="code" search={false} options={false} columns={columns} dataSource={dataSource}
            rowSelection={{
                selectedRowKeys,
                onChange: (keys, rows) => {
                    console.info('selected keys ', keys);
                    setSelectedRowKeys(keys);
                }
            }}
            toolbar={{
                menu: {
                    items: [{
                        key: 'batch',
                        label: <BatchOperation
                            onChange={() => {
                                console.info('change...');
                                setSelectedRowKeys([]);
                            }}
                            // onOk={() => onOk()} // 2
                            options={[
                                { value: 'A', label: '选项一' },
                                { value: 'B', label: '选项二', onOk: () => onOk() } // 1
                            ]}
                        />
                    }]
                }
            }}
        />
    )
};

export default Test;

const dataSource = [
    {
        name: '张三',
        code: 'A1'
    },
    {
        name: '李四',
        code: 'A2'
    }
];

如下图操作,进入页面直接选选项二,然后任意勾选之后点按钮,ok的输出不对。

React子组件回调父组件状态数据问题?

但是像下面这样操作,ok的输出是正确的。

但是使用注释// 2 位置的函数,不实用// 1的,无论怎么操作都是正常的。
请问下这是什么原因啊?

组件内部的任何函数,包括事件处理函数和 Effect,都是从它被创建的那次渲染中被「看到」的,所以引用的值任然是旧的。
所以无论是

onOk={() => onOk()}  还是  options={[ ..., { ..., onOk: () => onOk() }  ]}

结果都是

onOk={() => [] }    options={[ ..., { ..., onOk: () => [] }  ]}

你说的 注释// 2 位置的函数 是因为每次修改父组件的值都会刷新当前组件及其子组件

onOk={() => [1] }   也更新为  onOk={() => [2] }  了

options 里的方法表现 ‘ 异常 ‘ 是因为useState对其进行了缓存

selectedOption 仍然是初次创建结果 { ..., onOk: () => [] }
//const [selectedOption, setSelectedOption] = useState<OperationType>(options[0]);
const [selectedValue, setSelectedValue] = useState<T>(options[0]?.value);

//const { onOk = globalOk } = selectedOption;
const { onOk = globalOk } = options.find(({ value }) => value === selectedValue) || {};

我前面尝试改了下,不再直接存option完整的信息,而是只存value,然后需要的时候去options里去查找出来使用,使用这种方式,就都正常了。虽说改了效果是对了,但是不理解具体原因,看了你的回答后大体上是理解了一些了,就是对象被缓存了。感谢你的回答。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

1. JK下载官网所有资源来源于开发团队,加入会员即可下载使用!如有问题请联系右下角在线客服!
2. JK下载官方保障所有软件都通过人工亲测,为每位会员用户提供安全可靠的应用软件、游戏资源下载及程序开发服务。
3. JK开发团队针对会员诉求,历经多年拥有现今开发成果, 每款应用程序上线前都经过人工测试无误后提供安装使用,只为会员提供安全原创的应用。
4. PC/移动端应用下载后如遇安装使用问题请联系右下角在线客服或提交工单,一对一指导解决疑难。

JK软件下载官网 技术分享 React子组件回调父组件状态数据问题? https://www.jkxiazai.com/1536.html

JK软件应用商店是经过官方安全认证,保障正版软件平台

相关资源

官方客服团队

为您解决烦忧 - 24小时在线 专业服务