[英]React js invariant violation Hooks and Function Components
我將 Hooks 和 Function 組件一起使用。
在組件內部,我必須使用不變量,但是當我使用它時,它會給我帶來問題。
它給了我以下問題,即使我將這樣的簡單 boolean 條件作為不變條件:
invariant(false,..)
錯誤:
引發了跨域錯誤。 React 無法訪問開發中的實際錯誤 object。 請參閱......了解更多信息。
鏈接: 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>
);
}
您收到此錯誤是因為您嘗試訪問:
options[0].label
而 options 可能是一個空數組。
在不變量之前,檢查選項的長度是否大於0:
if(options.length > 0) {
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."
);
}
順便說一句,如果您在 CodeSandbox(chrome 上的 f12)和 go 中打開 DevTools 到控制台,您將看到一條信息更豐富的錯誤消息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.