Javascript 同时使用onChange和onKeyDown

Javascript 同时使用onChange和onKeyDown,javascript,reactjs,input,Javascript,Reactjs,Input,我正在寻找一种方法,将页码输入到输入标记中,然后仅在按下“enter”键时进行渲染,这样我在输入栏中输入的页码就会显示出来。但是,当使用onSearch时,每次我输入一些输入时,页面都会呈现,onKeyDown不允许我键入任何内容,也不能使用onSearch函数(或在其中调用的函数中)按下的键 有没有办法实现这个功能 import React from 'react'; import './App.scss'; import {createApiClient, Ticket} from './a

我正在寻找一种方法,将页码输入到输入标记中,然后仅在按下“enter”键时进行渲染,这样我在输入栏中输入的页码就会显示出来。但是,当使用onSearch时,每次我输入一些输入时,页面都会呈现,onKeyDown不允许我键入任何内容,也不能使用onSearch函数(或在其中调用的函数中)按下的键

有没有办法实现这个功能

import React from 'react';
import './App.scss';
import {createApiClient, Ticket} from './api';
 
export type AppState = {
    tickets?: Ticket[],
    hidden: {[key: string]: string}, //Obejct to keep hidden tickets
    search: string,
    pageInput: string,
    currentPage: number, 
}

const api = createApiClient();

export class App extends React.PureComponent<{}, AppState> {
    
    state: AppState = {
        hidden: {},
        search: '',
        currentPage: 1,
        pageInput: '',      
    }

    searchDebounce: any = null;

    async componentDidMount() {
        this.setState({
            tickets: await api.getTickets(this.state.currentPage, this.state.search) //pass the page and the search to show
        });
    }

    hideTicket = (id:string) => () => {}

    restoreTickets = () => {}

    
    renderTickets = (tickets: Ticket[]) => {

        this.hideTicket = (id:string) => () => { //Hide ticket, deconstruct previous hidden Object and add new id
            this.setState(prevState => ({
                hidden: {
                ...prevState.hidden, [id]: id
                }
            }));        
        }

        const ticketsToShow = tickets.filter((hiddenTicket) => !this.state.hidden[hiddenTicket.id]); //Filter if there are hidden tickets

        return (<ul className='tickets'>
            {ticketsToShow.map((ticket) => (<li key={ticket.id} className='ticket'>
                
                <div><button className='hide' type='button' onClick={this.hideTicket(ticket.id)}>Hide</button></div>
                <h5 className='title'>{ticket.title}</h5>
                <p className='content'>{ticket.content}</p>
                <footer>
                    <div className='meta-data'>By {ticket.userEmail} | { new Date(ticket.creationTime).toLocaleString()}</div>
                    <div id="tag-container">
                            {ticket.labels ? ticket.labels.map((label, index) => (
                                <span key={index} className="ticket-label">{label}</span>
                            )) : null}
                    </div>
                </footer>
            </li>))}
        </ul>);
    }

    onSearch = async (val: string, newPage?: number) => {
        
        clearTimeout(this.searchDebounce);

        this.searchDebounce = setTimeout(async () => {
            this.setState({
                search: val,
                currentPage: 1, //Go to the first page
                tickets: await api.getTickets(1, val)
            });
        }, 300);
    }

    onChange = async (page: number) => {}

    onJump = async(page: string) => {}

    onEnter = async (event: string) => {}

    render() {  
        const {tickets} = this.state;

        this.restoreTickets = () => {       //Clean the hidden tickets Object from tickets
            for(const id in this.state.hidden){
                delete this.state.hidden[id];
            }
            
            this.setState({
                hidden:{}
            });
        }

        this.onChange = async (page: number) => {
            this.restoreTickets()                   
            this.setState({
                currentPage: page,
                tickets: await api.getTickets(page, this.state.search) //Show next page
            });
        }

        this.onEnter = async (event: string) => {
            if(event.keyCode === 'enter')
            this.restoreTickets();
            this.setState({
                currentPage: parseInt(this.state.pageInput),
                pageInput: this.state.pageInput,
                tickets: await api.getTickets(parseInt(this.state.pageInput), this.state.search)
            })
        }


        return (<main>
            <h1>Tickets List</h1>
            <header>
                <input type="search" placeholder="Search..." onChange={(e) => this.onSearch(e.target.value)}/>
            </header>
            {Object.keys(this.state.hidden).length === 0 && tickets ? <div className='results'>Showing {tickets.length} results</div> 
            : tickets ? <div className='results-hidden'>Showing {tickets.length - Object.keys(this.state.hidden).length} results <span id="hidden-tag">({Object.keys(this.state.hidden).length} tickets hidden -
            <button className='restore-btn' onClick={this.restoreTickets}>restore</button>)</span></div> : null}    
            {tickets ? this.renderTickets(tickets) : <h2>Loading..</h2>}
            <div><input type='search' onChange={(e) => this.onEnter(e.target.value)}></input>{this.state.currentPage === 1 && this.state.tickets && this.state.tickets.length < 20 ? null :
             this.state.currentPage === 1 ? <div className="next-back-btn-container"><a className="next-btn" href="#" onClick={() => this.onChange(this.state.currentPage + 1)}>Next</a></div> :
             this.state.tickets && this.state.tickets.length < 20 ? <div className="next-back-btn-container"><a className="back-btn" href="#" onClick={() => this.onChange(this.state.currentPage - 1)}>Back</a></div>:
             <div className="next-back-btn-container">
                 <a className="back-btn" href="#" onClick={() => this.onChange(this.state.currentPage - 1)}>Back</a>
                 <a className="next-btn" href="#" onClick={() => this.onChange(this.state.currentPage + 1)}>Next</a>
             </div>}</div>
        </main>)

    }
}

export default App;
从“React”导入React;
导入“/App.scss”;
从“/api”导入{createApiClient,Ticket};
导出类型AppState={
票?:票[],
隐藏:{[key:string]:string},//Obejct保留隐藏票据
搜索:字符串,
pageInput:string,
当前页面:编号,
}
const api=createApiClient();
导出类应用程序扩展了React.PureComponent{
状态:AppState={
隐藏:{},
搜索:“”,
当前页面:1,
页面输入:“”,
}
searchDebounce:any=null;
异步组件didmount(){
这是我的国家({
票证:wait api.getTickets(this.state.currentPage,this.state.search)//传递要显示的页面和搜索
});
}
hideTicket=(id:string)=>()=>{}
restoreTickets=()=>{}
renderTickets=(票证:票证[])=>{
this.hideTicket=(id:string)=>()=>{//隐藏票据,解构以前隐藏的对象并添加新id
this.setState(prevState=>({
隐藏的:{
…prevState.hidden,[id]:id
}
}));        
}
const ticketsToShow=tickets.filter((hiddenTicket)=>!this.state.hidden[hiddenTicket.id]);//如果存在隐藏的票据,则进行筛选
返回(
    {ticketsToShow.map((ticket)=>(
  • 隐藏 {ticket.title}

    {ticket.content}

    通过{ticket.userEmail}{new Date(ticket.creationTime.toLocaleString()} {ticket.labels?ticket.labels.map((标签,索引)=>( {label} )):null}
  • )}
); } onSearch=async(val:string,newPage?:number)=>{ clearTimeout(this.searchDebounce); this.searchDebounce=setTimeout(异步()=>{ 这是我的国家({ 搜索:val, currentPage:1,//转到第一页 门票:等待api.getTickets(1,val) }); }, 300); } onChange=async(页码)=>{} onJump=async(页面:字符串)=>{} onEnter=async(事件:字符串)=>{} render(){ const{tickets}=this.state; this.restoreTickets=()=>{//从tickets中清除隐藏的tickets对象 for(此.state.hidden中的常量id){ 删除此.state.hidden[id]; } 这是我的国家({ 隐藏:{} }); } this.onChange=async(页码)=>{ 这个.restoreTickets() 这是我的国家({ 当前页:第页, 票证:wait api.getTickets(第页,this.state.search)//显示下一页 }); } this.onEnter=async(事件:字符串)=>{ 如果(event.keyCode==='enter') 这个。restoreTickets(); 这是我的国家({ currentPage:parseInt(this.state.pageInput), pageInput:this.state.pageInput, 票证:wait api.getTickets(parseInt(this.state.pageInput)、this.state.search) }) } 返回( 门票单 this.onSearch(e.target.value)}/> {Object.keys(this.state.hidden).length==0&&tickets?显示{tickets.length}结果 :tickets?显示{tickets.length-Object.keys(this.state.hidden).length}结果({Object.keys(this.state.hidden).length}tickets隐藏- 还原):null} {tickets?this.renderTickets(tickets):正在加载..} this.oneter(e.target.value)}>{this.state.currentPage==1&&this.state.tickets&&this.state.tickets.length<20?空: this.state.currentPage==1?: this.state.tickets&&this.state.tickets.length<20?: } ) } } 导出默认应用程序;