ReactJS-更新状态数组导致在其他组件中未定义

问题描述 投票:0回答:1

我有一个相当复杂的React应用。我有一个带有表单和提交按钮的模式。该表单附加了一个运行某些代码的提交处理程序。该代码的一部分是使用表单中的新数据更新订单状态数组。发生这种情况时,页面错误,而使用订单状态数组的其他组件则指出该错误为undefined。我不确定我是否错误地更新了状态,或者我的应用中是否有其他错误。我将订单和setOrders作为道具传递给各个组件。

这里是试图更新状态数组的模态组件。 SetOrders作为道具传递下来:

import ReactModal from 'react-modal';
import React, { useReducer } from 'react';
import CloseButton from './CloseButton';
import PropTypes from 'prop-types';
import { Scrollbars } from 'react-custom-scrollbars';
import { RadioGroup, Radio } from 'react-radio-group';

const initialState = {
    bagID: '',
    lineTechName: '',
    infoCorrect: '',
    materialCorrect: '',
    unwantedMaterials: '',
    unwantedMaterial: '',
    qualityAcceptable: '',
    program: 'Windows',
    sealingProperly: '',
    temperature: ''
};

const PackagerModal = (props) => {
    const {
        openPackager,
        activeOrder,
        setOrders,
        setOpenPackager,
        customStyles,
        setPackagerChecklistResults
    } = props;

    const [userInput, setUserInput] = useReducer(
        (state, newState) => ({ ...state, ...newState }),
        initialState
    );

    const handleTextChange = (evt) => {
        const { name, value } = evt.target;
        setUserInput({ [name]: value });
    };

    const handleRadioChange = (val, name) => {
        setUserInput({ [name]: val });
    };

    const handleSubmit = (evt) => {
        evt.preventDefault();

        // do database stuff
        // save to state for now
        // save form data to the packager checklist results state variable
        setPackagerChecklistResults(userInput);

        // create a new temp order so we don't mutate state and set the
        // packagerChecked field to true for this order
        const tempActiveOrder = JSON.parse(JSON.stringify(activeOrder));
        tempActiveOrder.packagerChecked = true;
        tempActiveOrder.packagerChecklist = userInput;
        console.log(tempActiveOrder);
        setOrders((prevOrders) => {
            prevOrders.map((order) => {
                return order.id === tempActiveOrder.id
                    ? tempActiveOrder
                    : order;
            });
        });

        // clear out form inputs
        setUserInput(initialState);

        // close package modal
        setOpenPackager(false);
    };

    return (
        <ReactModal
            isOpen={openPackager}
            style={customStyles}
            className={'order-details-modal'}
            closeTimeoutMS={1000}
        >
            <CloseButton setOpenModal={setOpenPackager} />
            <h2>Packager Order Checklist</h2>
            <Scrollbars autoHeight autoHeightMin={500} autoHeightMax={600}>
                <form className={'form'} onSubmit={handleSubmit}>
                    <!-- rest of the form inputs here are irrelavant -->
                    <input
                        className={'btn btn-primary d-block mx-auto mb-2'}
                        type={'submit'}
                        value={'Submit'}
                    />
                </form>
            </Scrollbars>
        </ReactModal>
    );
};

PackagerModal.propTypes = {
    openPackager: PropTypes.bool,
    setOpenPackager: PropTypes.func,
    customStyles: PropTypes.object,
    activeOrder: PropTypes.object,
    setPackagerChecklistResults: PropTypes.func
};

export default PackagerModal;

这是依靠订单状态数组在页面上显示订单的组件。订单被传递为道具:

import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { Droppable } from 'react-beautiful-dnd';
import styled from 'styled-components';
import Order from '../order/Order';
import { Scrollbars } from 'react-custom-scrollbars';
//import { ScheduleContext } from '../../schedule-context';
import '../../App.scss';

// border-right-width set below to fix an issue with doubled borders between columns
const MyOrder = styled.div`
    transition: background-color 0.5s ease;
    background-color: ${(props) =>
        props.isDraggingOver ? '#fffbc9' : '#ffffff'};
    border-style: ${(props) =>
        props.isDraggingOver ? 'dashed' : 'solid'};
    border-right-width: ${(props) =>
        props.isDraggingOver ? '3px' : '0'};
`;
const OrderColumn = (props) => {
    const {
        columnId,
        line,
        setOpenLineModal,
        setLineModalHeader,
        orders
    } = props;
    //const orders = useContext(ScheduleContext).orders;
    console.log('orderCol orders: ', orders);
    const orderIDs = props.orderIDs;

    const openLineModal = () => {
        if ((line === 'middle' || line === 'last') && orderIDs.length) {
            setLineModalHeader(props.title + ' Orders');
            setOpenLineModal(true);
        }
    };

    return (
        <Droppable droppableId={columnId}>
            {(provided, snapshot) => {
                return (
                    <MyOrder
                        className={'col order-column ' + props.line}
                        ref={provided.innerRef}
                        {...provided.droppableProps}
                        isDraggingOver={snapshot.isDraggingOver}
                        key={columnId}
                    >
                        <Scrollbars
                            // This will activate auto hide
                            autoHide
                            // Hide delay in ms
                            autoHideTimeout={1000}
                            // Duration for hide animation in ms.
                            autoHideDuration={200}
                        >
                            <h3
                                className={
                                    (line === 'middle' || line === 'last') &&
                                    orderIDs.length
                                        ? 'text-center title hand-cursor'
                                        : 'text-center title'
                                }
                                onClick={() => openLineModal()}
                            >
                                {props.title} <span>({orderIDs.length})</span>
                            </h3>
                            <div className={'orders'}>
                                {orderIDs &&
                                    orderIDs.map((orderID, index) => {
                                        const order = orders.find(
                                            (o) => o.id === orderID
                                        );

                                        return (
                                            <Order
                                                key={orderID}
                                                order={order}
                                                index={index}
                                            />
                                        );
                                    })}
                            </div>
                        </Scrollbars>
                        {provided.placeholder}
                    </MyOrder>
                );
            }}
        </Droppable>
    );
};

OrderColumn.propTypes = {
    orders: PropTypes.array,
    orderIDs: PropTypes.array,
    columnId: PropTypes.string.isRequired,
    line: PropTypes.string.isRequired,
    title: PropTypes.string.isRequired,
    setOpenLineModal: PropTypes.func.isRequired,
    setLineModalHeader: PropTypes.func.isRequired
};

export default OrderColumn;

reactjs state
1个回答
2
投票

您只是忘了在setOrders函数中返回新的映射数组:

setOrders((prevOrders) => {
            // return this map
            return prevOrders.map((order) => {
                return order.id === tempActiveOrder.id
                    ? tempActiveOrder
                    : order;
            });
        });

此外,我会创建一个像这样的新数组:const newArr = [...oldArr]而不是使用JSON.parseJSON.stringify,因为JSON字符串化和解析更加昂贵,而且我认为它看起来更干净,但个人喜好是全部。

或者,对于对象:

const newObj = { ...oldObj }
© www.soinside.com 2019 - 2024. All rights reserved.