【发布时间】:2021-08-10 14:21:40
【问题描述】:
我几乎放弃了这个错误。 我只是无法在搜索输入中输入“S”。
键盘工作正常。
下面的沙盒。
https://codesandbox.io/s/jolly-raman-61zbx?file=/src/App.js
沙盒代码:
import {
Box,
FormControl,
InputAdornment,
ListItem,
Menu,
TextField,
withStyles
} from "@material-ui/core";
import {
clamp,
difference,
includes,
intersection,
join,
map,
union
} from "lodash";
import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
import { FixedSizeList } from "react-window";
import Fuse from "fuse.js";
import React from "react";
import SearchIcon from "@material-ui/icons/Search";
import memoize from "memoize-one";
const styles = {
popoverPaper: {
width: "100%"
}
};
const fuseOptions = {
includeScore: true
};
const initialSearchState = {
searchValue: ""
};
const getCheckedList = (list) => (!!list ? list : []);
class VirtualisedSelector extends React.Component {
constructor(props) {
super(props);
this.state = {
anchorEl: null,
...initialSearchState
};
}
getSearchList = memoize((list, searchValue) => {
const fuse = new Fuse(list, fuseOptions);
return !!searchValue ? map(fuse.search(searchValue), (o) => o.item) : list;
});
handleSearch = (event) => {
this.setState({
...this.state,
searchValue: event.target.value
});
};
getCleanSelectedValues = memoize((currentSelectedValues, list) =>
intersection(currentSelectedValues, list)
);
getNewMultipleValue = (currentSelectedValues, clickedItemValue) =>
includes(currentSelectedValues, clickedItemValue)
? difference(currentSelectedValues, [clickedItemValue])
: union(currentSelectedValues, [clickedItemValue]);
getNewSingleValue = (currentSelectedValues, clickedItemValue) =>
includes(currentSelectedValues, clickedItemValue) ? [] : [clickedItemValue];
getNewValue = (currentSelectedValues, clickedItemValue, list, multiple) =>
multiple
? this.getNewMultipleValue(
this.getCleanSelectedValues(currentSelectedValues, list),
clickedItemValue
)
: this.getNewSingleValue(currentSelectedValues, clickedItemValue);
handleChange = (currentSelectedValues, list, multiple) => (event) => {
this.setState({
anchorEl: null
});
const clickedItemValue = event.target.getAttribute("value");
const newValue = this.getNewValue(
currentSelectedValues,
clickedItemValue,
list,
multiple
);
this.props.onSelect(newValue);
};
getTextFieldDisplayValue = (value, list, labelMap) =>
join(
map(this.getCleanSelectedValues(value, list), (e) => labelMap[e] ?? e),
", "
);
handleMenuOpen = (event) => {
this.setState({ anchorEl: event.currentTarget });
};
handleMenuClose = (event) => {
this.setState({ anchorEl: null, ...initialSearchState });
};
renderRow = () => ({ index, style }) => {
const { multiple, value, list, labelMap } = this.props;
const { searchValue } = this.state;
const searchList = this.getSearchList(list, searchValue);
const cleanSelectedValues = this.getCleanSelectedValues(value, list);
const listItem = searchList[index];
return (
<ListItem
value={listItem}
key={listItem}
selected={includes(value, listItem)}
onClick={this.handleChange(cleanSelectedValues, list, multiple)}
style={style}
>
{labelMap?.[listItem] || listItem}
</ListItem>
);
};
render() {
const {
value,
list,
name,
label,
labelMap,
required = false,
classes
} = this.props;
const { searchValue } = this.state;
const formControlClassNames = this.props?.classes?.formControl;
const searchList = this.getSearchList(getCheckedList(list), searchValue);
const nItems = searchList.length;
const stringHeight = 46;
const fixedSizeListHeight = stringHeight * clamp(nItems, 1, 10);
return (
<FormControl className={formControlClassNames} fullWidth>
<TextField
onClick={this.handleMenuOpen}
variant="outlined"
required={required}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<ArrowDropDownIcon />
</InputAdornment>
)
}}
value={this.getTextFieldDisplayValue(value, list, labelMap)}
multiline
type="text"
name={name}
label={label}
fullWidth
/>
<Menu
anchorEl={this.state.anchorEl}
keepMounted
open={Boolean(this.state.anchorEl)}
onClose={this.handleMenuClose}
PopoverClasses={{ paper: classes.popoverPaper }}
>
{/* Search */}
<Box p={1}>
<TextField
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
)
}}
type="text"
label={"Search"}
value={searchValue}
onChange={this.handleSearch}
fullWidth
/>
</Box>
{/* Virtualized list */}
<FixedSizeList
height={fixedSizeListHeight}
width={"100%"}
itemSize={stringHeight}
itemCount={nItems}
>
{this.renderRow()}
</FixedSizeList>
</Menu>
</FormControl>
);
}
}
VirtualisedSelector.defaultProps = {
value: "",
list: [],
name: "",
label: "",
labelMap: {},
required: false
};
export default withStyles(styles)(VirtualisedSelector);
【问题讨论】:
-
请在问题中直接包含相关代码。您可以链接到场外以获取支持资源,但问题应该无需离开即可回答。
-
我还没有设法找到问题所在,但我发现:1) 没有
<Menu>组件它可以正常工作,这意味着问题可能存在 2) 行为类似于@ 987654324@ 用作键盘导航的热键。
标签: javascript reactjs material-ui