首页 > 解决方案 > 获取 SetState 的值未在反应中更新

问题描述

我有一个回调函数,它在 SetState 中更新我的数组,它工作正常,正如我在 handleDaysValueChange 的控制台日志中看到的那样,一切都很好。但是当我尝试在另一个函数中访问它时,即 handleValuesChange 值不是最新的。我错过了异步或其他东西。

import React from 'react';
import PropTypes from 'prop-types';
import AppService from 'services/app-service';
import Enum from 'enum';
import { ApiData } from 'data';
import { isEmpty, boolValue } from 'core/type-check';
import { notifySuccess } from 'core/errors';
import { withDrawerForm } from 'components/_hoc';
import { ExtendedAvatar } from 'components/extended-antd';
import { Tabs } from 'antd';
import { FormTemplateAudit } from '../templates';
import ShiftRosterFormDetails from './shiftroster-form-details';
import Item from 'antd/lib/list/Item';

const { TabPane } = Tabs;

class ShiftRosterForm extends React.Component {
    constructor(props) {
        super(props);
        this.formInputRef = React.createRef();

        this.state = {
            daysValue:[]
        };
        this.handleDaysValueChange = this.handleDaysValueChange.bind(this);
       
    }
    
    handleDaysValueChange(daysValues) {
        
        this.setState({ daysValue: daysValues }, () => {
            console.log("Data" + this.props.customData);
            console.log("Hello World " + JSON.stringify(this.state.daysValue));
        });
    }

    componentDidMount() {
        // Update the parent form state with a reference to the
        // formInputRef so we can call this later for validation
        // before saving the data to the server.
        const { onFormStateChange } = this.props;
        onFormStateChange({ formInputRef: this.formInputRef.current });
    }

    //Shift Roster Detail

    handleValuesChange = (props, changedValues, allValues) => {
        // Update the parent form state with the changed item
        // details and mark the form as dirty
        const { itemData, onFormStateChange } = this.props;
        console.log("Hey" + this.state.daysValue);
        onFormStateChange({
            isFormDirty: true,
            itemData: {
                ...itemData,
                ...changedValues,
                ...this.state.daysValue
            }
        });
    }

    render() {
        const { itemData, customData } = this.props;
        const isSR = (!isEmpty(itemData) && itemData.id > 0);

        return (
            <Tabs className="bhp-tabs" defaultActiveKey="1" animated={false}>
                <TabPane key="1" tab="Details">
                    <ShiftRosterFormDetails
                        ref={this.formInputRef}
                        dataSource={itemData}
                        onValuesChange={this.handleValuesChange}
                        handleDaysValueChange={this.handleDaysValueChange}
                    />
                </TabPane>
                <TabPane key="2" tab="Audit" disabled={!isSR}>
                    <FormTemplateAudit
                        itemData={itemData}
                    />
                </TabPane>
            </Tabs>
        );
    }
}

ShiftRosterForm.propTypes = {
    itemId: PropTypes.number,                 // Passed in by the HOC. The loaded Shift Roster id
    itemData: PropTypes.object,               // Passed in by the HOC. The loaded Shift Roster data
    customData: PropTypes.object,             // Temporary store to hold the changed Shift Roster
    isFormDirty: PropTypes.bool,              // Passed in by the HOC. Flags if the parent form is dirty
    isLoading: PropTypes.bool,                // Passed in by the HOC. Flags if the parent form is loading
    daysValue: PropTypes.object,
    onFormStateChange: PropTypes.func        // Passed in by the HOC. Callback to update the parent form state.
    
};

ShiftRosterForm.defaultProps = {
    itemId: -1,
    itemData: {},
    customData: {},
    isFormDirty: false,
    isLoading: false,
    daysValue: {},
    onFormStateChange() { }
};

const ShiftRosterFormTitle = ({ data }) => {
    const name = (!isEmpty(data) && data.id > 0) ? `${data.name}` : 'New Shift Roster';//`${data.name}`
    return isEmpty(data)
        ? <ExtendedAvatar type="icon" size="large" />
        : <span><ExtendedAvatar name={name} type="letter" size="large" />{name}</span>
}

const saveShiftRoster = (shiftrosterId, shiftroster, rosterdays) => {
    return ApiData.saveShiftRoster(shiftrosterId, shiftroster, rosterdays)
        .then(response => {
            notifySuccess('Save Successful', 'Site Work Package saved successfully');
            return response;
        })
        .catch(error => {
            throw error;
        });
}

const saveForm = (formState, setFormState) => {
    const { isFormDirty, itemData, customData, formInputRef } = formState;
    const typeName = "Dynamic";
    const actualType = itemData.type;
    let rosterdays = [];
    if (actualType !== typeName) {
        rosterdays = GetDaysForRoster(itemData);
        console.log("My Values" + JSON.stringify(rosterdays));
    }
    
    const shiftRosterId = itemData.id;
    const isExistingShiftRoster = shiftRosterId > 0;
    
    return new Promise((resolve, reject) => {
        if (isExistingShiftRoster && !isFormDirty) {
            // No Changes
            notifySuccess('Save Successful', 'Site Work Package saved successfully');
            resolve(itemData);
        }
        else {
            // Validate and Save
            formInputRef.validateFields((error, values) => {
                if (!error) {
                    // Form validated successfully.
                    // Save form changes
                    
                    const shiftrosterRecord = saveShiftRoster(shiftRosterId, values, rosterdays);
                    resolve(shiftrosterRecord);
                }
                else {
                    // Form validation error.
                    // Return data as is.
                    resolve(itemData);
                }
            });
        }
    });
}
const GetDaysForRoster = (itemsData) => {
    const result = [];
    const keys = Object.keys(itemsData);
    for (const k in keys) {
        if (Number(k) == k) {
            result[k] = itemsData[k]
        }
    }
    return result.filter(function (el) { return el != null });
}

const WrappedShiftRosterForm = withDrawerForm({
    containerClassName: 'bhp-equipment-type-form',
    title: (record) => <ShiftRosterFormTitle data={record} />,
    onLoad: (itemId, setFormState) => ApiData.getShiftRoster(itemId),
    onSave: (formState, setFormState) => { return saveForm(formState, setFormState); },
    canView: () => AppService.hasAccess({ [Enum.SecurityModule.EquipmentTypeDetails]: [Enum.SecurityPermission.Read] }),
    canCreate: () => AppService.hasAccess({ [Enum.SecurityModule.EquipmentTypeDetails]: [Enum.SecurityPermission.Create] }),
    canUpdate: () => AppService.hasAccess({ [Enum.SecurityModule.EquipmentTypeDetails]: [Enum.SecurityPermission.Update] })
})(ShiftRosterForm);

WrappedShiftRosterForm.propTypes = {
    containerClassName: PropTypes.string,
    itemId: PropTypes.number,
    visible: PropTypes.bool,
    onSave: PropTypes.func,
    onClose: PropTypes.func
};

WrappedShiftRosterForm.defaultProps = {
    containerClassName: null,
    itemId: -1,
    visible: false,
    onSave() { },
    onClose() { }
};

export default WrappedShiftRosterForm;

//ShiftRosterFormDetails

import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { ApiData } from 'data';
import { Form, Input, Select, Button, space, InputNumber } from 'antd';
import ShiftDays from './shiftdays'

const ShiftRosterFormDetails = ({ form, dataSource, onValueChange, handleDaysValueChange }) => {
    const { getFieldDecorator } = form;
    
    const formLayout = {
        labelCol: {
            xs: { span: 24 },
            sm: { span: 6 },
        },
        wrapperCol: {
            xs: { span: 24 },
            sm: { span: 12 },
        },
    };
    console.log("My datasource" + dataSource.shiftRosterDays);
    //const daysRoster = dataSource.shiftRosterDays || [{ daysIn: 1, daysOut: 1, category: "Day Shift" }];
    const [inputList, setInputList] = useState([{ daysIn: 1, daysOut: 1, category: "Day Shift" }]);
    const [selectedType, setSelectedType] = useState(dataSource.type || 'Fixed Single');
    const [isTotalDaysRequired, SetTotalDaysRequired] = useState(dataSource.type === 'Dynamic' ? true : false);
    const [isTotalDaysRequiredMessage, setIsTotalDaysRequiredMessage] = useState(dataSource.type === 'Dynamic' ? 'Please enter the Total Days' : '');
    
    const handleTypeChanged = (value, e) => {
        setSelectedType(value);
        if (value === "Dynamic") {
            SetTotalDaysRequired(true);
            setIsTotalDaysRequiredMessage('Please enter the Total Days');
        }
        if (value === "Fixed Single") {
            if (inputList.length > 1) {
                const list = [...inputList];
                console.log("Total" + inputList.length);
                list.splice(1, inputList.length);
                setInputList(list);
                console.log("My List" + JSON.stringify(list));
                console.log("Input List" + JSON.stringify(inputList));
                handleDaysValueChange(list);
            }
        }
        else {
            SetTotalDaysRequired(false);
            setIsTotalDaysRequiredMessage('');
        }
    };

    
    return (
         
        <div className='bhp-equipment-type-form-details bhp-content-box-shadow'>
            <Form {...formLayout}>
                <Form.Item label='Name' hasFeedback>
                    {getFieldDecorator('name', {
                        initialValue: dataSource.name,
                        rules: [{
                            required: true,
                            message: 'Please enter the Name'
                        }],
                    })(
                        //disabled={dataSource.id > 0}
                        <Input placeholder='Name' />
                    )}
                </Form.Item>
                <Form.Item label='Status' hasFeedback>
                    {getFieldDecorator('status', {
                        initialValue: dataSource.status,
                        rules: [{
                            required: true,
                            message: 'Please enter the Status'
                        }],
                    })(
                        <Select>
                            <Select.Option value="Active">Active</Select.Option>
                            <Select.Option value="InActive">InActive</Select.Option>
                        </Select>
                    )}
                </Form.Item>
                <Form.Item label='Type' hasFeedback>
                    {getFieldDecorator('type', {
                        initialValue: dataSource.type || 'Fixed Single',
                        rules: [{
                            required: true,
                            message: 'Please select the Type'
                        }],
                    })(
                        <Select onChange={handleTypeChanged}>
                            <Select.Option value="Fixed Single">Fixed Single</Select.Option>
                            <Select.Option value="Fixed Multiple">Fixed Multiple</Select.Option>
                            <Select.Option value="Dynamic">Dynamic</Select.Option>
                        </Select>
                    )}
                </Form.Item>
                <Form.Item label='Total Days' hasFeedback style={selectedType === 'Dynamic' ? { display: '' } : { display: 'none' }}>
                    {getFieldDecorator('totaldays', {
                        initialValue: dataSource.totalDays,
                        rules: [{
                            required: isTotalDaysRequired,
                            message: isTotalDaysRequiredMessage
                        }],
                    })(
                        <InputNumber min={1} max={365} />
                    )}
                </Form.Item>
                
                <ShiftDays inputList={inputList} setInputList={setInputList} selectedType={selectedType} handleDaysValueChange={handleDaysValueChange} getFieldDecorator={getFieldDecorator} />
              
            </Form>
        </div>
        
    )};

const onFieldsChange = (props, changedFields, allFields) => {
    if (props.onFieldsChange) {
        props.onFieldsChange(props, changedFields, allFields);
    }
};

const onValuesChange = (props, changedValues, allValues) => {
    if (props.onValuesChange) {
        props.onValuesChange(props, changedValues, allValues);
    }
};

ShiftRosterFormDetails.propTypes = {
    form: PropTypes.object,
    dataSource: PropTypes.object,
    onFieldsChange: PropTypes.func,
    onValuesChange: PropTypes.func
};

ShiftRosterFormDetails.defaultProps = {
    form: {},
    dataSource: {},
    onFieldsChange() { },
    onValuesChange() { }
};

export default Form.create({
    onValuesChange,
    onFieldsChange
})(ShiftRosterFormDetails);

标签: javascriptreactjs

解决方案


推荐阅读