作为技术测试的一部分,有人要求我在React中编写一个自动完成输入。我已经做到了,但是现在我想添加使用箭头键在渲染列表中上下导航的功能。我已经做了一些广泛的Google搜索,除了npm软件包之外,什么都没有发现React专用。
需要明确的是,我正在寻找类似React的东西:https://www.w3schools.com/howto/howto_js_autocomplete.asp
我基本上只需要箭头按钮功能,其他所有功能都可以正常工作。
欢呼
这是我尝试过但无法正常工作的示例。
export default class Example extends Component {
constructor(props) {
super(props)
this.handleKeyDown = this.handleKeyDown.bind(this)
this.state = {
cursor: 0,
result: []
}
}
handleKeyDown(e) {
const { cursor, result } = this.state
// arrow up/down button should select next/previous list element
if (e.keyCode === 38 && cursor > 0) {
this.setState( prevState => ({
cursor: prevState.cursor - 1
}))
} else if (e.keyCode === 40 && cursor < result.length - 1) {
this.setState( prevState => ({
cursor: prevState.cursor + 1
}))
}
}
render() {
const { cursor } = this.state
return (
<Container>
<Input onKeyDown={ this.handleKeyDown }/>
<List>
{
result.map((item, i) => (
<List.Item
key={ item._id }
className={cursor === i ? 'active' : null}
>
<span>{ item.title }</span>
</List.Item>
))
}
</List>
</Container>
)
}
}
这是我的代码:
class Search extends Component {
constructor(props) {
super(props);
this.state = {
location: '',
searchName: '',
showSearch: false,
cursor: 0
};
}
handleKeyPress = e => {
const { cursor, searchName } = this.state;
// arrow up/down button should select next/previous list element
if (e.keyCode === 38 && cursor > 0) {
this.setState(prevState => ({
cursor: prevState.cursor - 1
}));
} else if (e.keyCode === 40 && cursor < searchName.length - 1) {
this.setState(prevState => ({
cursor: prevState.cursor + 1
}));
}
};
render() {
const { searchName, location } = this.state;
return (
<div className="Search">
<h1>Where are you going?</h1>
<form id="search-form" onSubmit={this.handleSubmit}>
<label htmlFor="location">Pick-up Location</label>
<input
type="text"
id="location"
value={location}
placeholder="city, airport, station, region, district..."
onChange={this.handleChange}
onKeyUp={this.handleKeyUp}
onKeyDown={this.handleKeyPress}
/>
{this.state.showSearch ? (
<Suggestions searchName={searchName} />
) : null}
<button value="submit" type="submit" id="search-button">
Search
</button>
</form>
</div>
);
}
从静态API呈现列表的代码:
.then(res =>
this.setState({
searchName: res.data.results.docs.map(array => (
<a href="#">
<div
key={array.ufi}
className="locations"
>
{array.name}
</div>
</a>
))
})
);
答案 0 :(得分:0)
由于您将函数定义为handleKeyDown(e) {...}
,因此上下文this
并不指向类实例的上下文,因此该上下文将由onKeyDown提供(我假设它是window
this
)
因此,您有2种方法:
将您的函数声明为handleKeyDown = (e) => {...}
将handleKeyDown上下文绑定到组件实例,例如onKeyDown={this.handleKeyDown.bind(this)}
此外,别忘了您可能需要一个mod items.length计数器,这意味着当您按下并选择了最后一个项目时,它将转到第一个项目。
您的api用法(将markdown存储到状态中)只是一件可怕的事情。您再也无法访问这些字符串,而是将其另存为纯数组。将其传递到您需要的位置,然后用它在此处创建jsx。
此外,您根本不会使用状态中的光标。