src/defaultRenderErrorSummary.js (86 lines of code) (raw):
import React from 'react';
import PropTypes from 'prop-types';
const focusField = fieldId => {
const element = document.getElementById(fieldId);
if (element && element.focus) {
element.focus();
const rect = element.getBoundingClientRect();
window.scrollTo(0, rect.y);
}
};
const renderItem = (id, label, message) => {
return (
<li key={id}>
<a
onClick={e => {
e.preventDefault();
focusField(id);
}}
href={`#${id}`}
>
{label}: {message}
</a>
</li>
);
};
const renderField = field => {
if (!field.errors || !field.errors.length) {
return null;
}
const error = field.errors[0];
if (error && typeof error === 'string') {
return [renderItem(field.fieldId, field.label, error)];
}
const items = [];
if (error && error.message) {
items.push(renderItem(field.fieldId, field.label, error.message));
}
if (error && error.children && error.children.length) {
error.children.forEach(child => {
items.push(renderItem(field.fieldId, child.summaryLabel, child.message));
});
}
return items;
};
class ErrorSummary extends React.Component {
static propTypes = {
submitCount: PropTypes.number.isRequired,
summaryData: PropTypes.array.isRequired,
};
constructor(props) {
super(props);
this.state = {
submitCount: this.props.submitCount,
summaryData: this.props.summaryData,
};
}
static getDerivedStateFromProps(props, state) {
if (props.submitCount !== state.submitCount) {
return {
submitCount: props.submitCount,
summaryData: props.summaryData,
};
}
return null;
}
render() {
return (
<ul>
{this.state.summaryData.reduce((items, field) => {
return [
...items,
...renderField(field),
];
}, [])}
</ul>
);
};
}
/* eslint-disable react/prop-types */
const defaultRenderErrorSummary = ({summaryData, submitCount}) => {
return (
<ErrorSummary submitCount={submitCount} summaryData={summaryData} />
);
};
/* eslint-enable react/prop-types */
export default defaultRenderErrorSummary;