У меня довольно сложное приложение 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;