Я использую крючки и функциональные компоненты вместе.
Внутри компонентов я должен использовать инвариант, но когда я его использую, это вызывает у меня проблемы.
Это дает мне следующеепроблема, даже если я поставил простое логическое условие, подобное этому, в качестве инвариантного условия:
invariant(false,..)
Ошибка:
Произошла перекрестная ошибка.React не имеет доступа к фактическому объекту ошибки в разработке.Смотрите .... для получения дополнительной информации.
Ссылка: codesandbox
Код:
import React, { useState } from "react";
import PropTypes from "prop-types";
import deburr from "lodash/deburr";
import Downshift from "downshift";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "../MyTextField/MyTextField";
import { Paper, MenuItem, Chip } from "@material-ui/core";
import invariant from "invariant";
import { isPlainObject } from "lodash";
function getStringLabelKey(labelKey) {
return typeof labelKey === "string" ? labelKey : "label";
}
function getOptionLabel(option, labelKey) {
//console.log("getOptionLabel", option, labelKey);
if (option.paginationOption || option.customOption) {
return option[getStringLabelKey(labelKey)];
}
let optionLabel;
if (typeof option === "string") {
optionLabel = option;
}
if (typeof labelKey === "function") {
// This overwrites string options, but we assume the consumer wants to do
// something custom if `labelKey` is a function.
optionLabel = labelKey(option);
} else if (typeof labelKey === "string" && isPlainObject(option)) {
optionLabel = option[labelKey];
}
invariant(
typeof optionLabel === "string",
"One or more options does not have a valid label string. Check the " +
"`labelKey` prop to ensure that it matches the correct option key and " +
"provides a string for filtering and display."
);
return optionLabel;
}
function renderInput(inputProps) {
const { InputProps, classes, ref, ...other } = inputProps;
return (
<span className={classes.noDisplay}>
<TextField
InputProps={{
inputRef: ref,
classes: {
root: classes.inputRoot,
input: classes.inputInput
},
...InputProps
}}
{...other}
/>
</span>
);
}
renderInput.propTypes = {
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object.isRequired,
InputProps: PropTypes.object
};
function renderSuggestion(suggestionProps) {
const {
suggestion,
itemProps,
//selectedItem,
renderMenuItemChildren
} = suggestionProps;
return (
<MenuItem
{...itemProps}
key={suggestion.email}
component="div"
style={{
fontWeight: 400
}}
>
{getOptionLabel(suggestion, renderMenuItemChildren)}
</MenuItem>
);
}
IntegrationDownshift.defaultProps = {
labelKey: "label",
renderMenuItemChildren: "label",
placeholder: "Search...",
label: "Search",
noFound: "No matches found.",
fullWidth: false
};
renderSuggestion.propTypes = {
highlightedIndex: PropTypes.oneOfType([
PropTypes.oneOf([null]),
PropTypes.number
]).isRequired,
index: PropTypes.number.isRequired,
itemProps: PropTypes.object.isRequired,
selectedItem: PropTypes.string.isRequired,
suggestion: PropTypes.shape({
label: PropTypes.string.isRequired
}).isRequired,
fullWidth: PropTypes.bool
};
function getSuggestions(value, { options, showEmpty = false } = {}) {
const inputValue = deburr(value.trim()).toLowerCase();
const inputLength = inputValue.length;
let el = inputLength === 0 && !showEmpty ? [] : options;
return el;
}
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
height: 50
},
container: {
flexGrow: 1,
position: "relative"
},
paper: {
position: "absolute",
zIndex: 1,
marginTop: theme.spacing(1),
left: 0,
right: 0
},
chip: {
margin: theme.spacing(0.5, 0.25)
},
inputRoot: {
flexWrap: "wrap"
},
inputInput: {
width: "auto",
flexGrow: 1
},
divider: {
height: theme.spacing(2)
},
noDisplay: {
"& .MuiInputBase-inputAdornedEnd": {
display: "none !important"
},
"& .MuiChip-root": {
//width: "100%",
justifyContent: "flex-start !important"
},
"& .MuiChip-deleteIcon": {
position: "absolute",
right: "5px"
}
},
myClass: {
width: "100%",
backgroundColor: "#ffccaa"
}
}));
export default function IntegrationDownshift({
options,
onSearch,
onChange,
selectedItem,
labelKey,
renderMenuItemChildren,
placeholder,
label,
noResult,
noFound,
fullWidth,
backgroundColorChip,
colorTextChip
}) {
const [search, setSearch] = useState("");
const classes = useStyles();
function handleInputChange(event) {
//console.log("handleInputChangeINT", event.target.value);
onSearch(event.target.value);
}
function handleChange(event) {
//console.log("handleChangeINT", event);
onChange(event);
}
function invCheck() {
console.log("label", options[0] && options[0].label);
invariant(
typeof options[0].label === "string",
"One or more options does not have a valid label string. Check the " +
"`labelKey` prop to ensure that it matches the correct option key and " +
"provides a string for filtering and display."
);
}
invCheck();
return (
<div className={classes.root}>
<Downshift
id="downshift-options"
onChange={handleChange}
selectedItem={selectedItem}
//itemToString={item => (item ? item.value : search)}
itemToString={item => search}
>
{({
clearSelection,
getInputProps,
getItemProps,
getLabelProps,
getMenuProps,
highlightedIndex,
inputValue,
isOpen,
openMenu,
selectedItem
}) => {
const { onBlur, onChange, onFocus, ...inputProps } = getInputProps({
onChange: event => {
//console.log("onChangeDINT", event.target.value);
setSearch(event.target.value);
if (event.target.value === "") {
clearSelection();
}
},
onFocus: openMenu,
placeholder
});
return (
<div className={classes.container}>
{renderInput({
fullWidth: true,
classes,
label,
InputLabelProps: getLabelProps({ shrink: true }),
InputProps: {
endAdornment: selectedItem !== null && (
<Chip
key={1}
tabIndex={-1}
label={getOptionLabel(selectedItem, labelKey)}
className={classes.chip}
onDelete={() => clearSelection()}
style={{
width: fullWidth && "100%",
backgroundColor: backgroundColorChip,
color: colorTextChip
}}
/>
),
onBlur,
onChange: event => {
handleInputChange(event);
onChange(event);
},
onFocus
},
inputProps
})}
<div {...getMenuProps()}>
{isOpen ? (
<Paper className={classes.paper} square>
{getSuggestions(inputValue, {
options,
showEmpty: false
}).map((suggestion, index) =>
renderSuggestion({
suggestion,
index,
renderMenuItemChildren,
itemProps: getItemProps({
item: suggestion
}),
highlightedIndex,
selectedItem
})
)}
{inputValue.length > 0 &&
getSuggestions(inputValue, { options, showEmpty: true })
.length === 0 && (
<MenuItem
key={"noFound"}
component="div"
style={{
fontWeight: 400
}}
onClick={() => {
if (noResult !== undefined) noResult(true);
}}
>
{noFound}
</MenuItem>
)}
</Paper>
) : null}
</div>
</div>
);
}}
</Downshift>
</div>
);
}