如何捕获输入更改事件但不是每次按键?

时间:2016-11-02 17:41:44

标签: reactjs

我有一个由输入(jobId)和span(jobDescription)组成的简单组件。当用户输入jobId时,组件进行ajax调用以填写描述。听起来很容易。但这是我的问题,我编写它的方式,该组件使用一堆浪费的调用来查找每个按键的jobDescription。

我尝试将查找更改为onBlur而不是onChange,但后来我错过了#34;初始加载" (从父项传入jobId时的初始渲染)。因此,首次打开表单时,jobDescription为空白。

所以这就是我需要的:

  1. 当用户键入jobId时,查找相应的jobDescription。但不一定是每次关键的中风。
  2. 当父进入jobId时,它还应该查找相应的jobDescription。
  3. 这是现在的组件:

    import React from "react";
    
    type Props = {
        jobId:string,
        onChange:(jobId: string)=>void
    }
    
    type State = {
        description:string
    }
    
    export default class JobComponent extends React.Component {
    
        props: Props;
        state: State;
    
        constructor(props: Props) {
            super(props);
            this.state = {
                description: ""
            }
        }
    
        componentWillReceiveProps(nextProps: Props) {
            if (nextProps.jobId != this.props.jobId) {
                this.loadDescription(nextProps.jobId)
                    .then((description)=> {
                        this.setState({description});
                    });
            }
        }
    
        onChangeInternal = (event)=> {
            const jobId = event.target.value;
            this.props.onChange(jobId);
            this.loadDescription(jobId)
                .then((description)=> {
                    this.setState({description});
                });
        };
    
        render() {
            return <div>
                <input className="job-id" value={this.props.jobId} onChange={this.onChangeInternal}/>
                <span className="job-description">{this.state.description}</span>
            </div>;
        }
    
        loadDescription = (jobId): Promise<string> => {
            return new Promise((resolve) => {
                if (!jobId) resolve("");
                else
                    fetch('/components/job-picker/jobService.jsp?jobId=' + jobId)
                        .then((response) => {
                            return response.json();
                        })
                        .then((job) => {
                            resolve(job.description);
                        });
            });
        };
    }
    

    以下是父组件的示例:

    import React from "react";
    import JobComponent from "./JobComponent";
    
    export default class FormTest extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                name: "Dave",
                jobId: "360107",
                age: 50
            }
        }
        render() {
            const onNameChange = (event)=> {
                this.setState({name: event.target.value});
            };
            const onAgeChange = (event)=> {
                this.setState({age: event.target.value});
            };
            const onJobIdChange = (jobId)=> {
                this.setState({jobId});
            };
            return (
                <div>
                    Name<input value={this.state.name} onChange={onNameChange}/><br/>
                    JobId<JobComponent jobId={this.state.jobId} onChange={onJobIdChange}/><br/>
                    Age<input value={this.state.age} onChange={onAgeChange}/><br/>
                </div>
            );
        }
    }
    

    那么,假设谁理解我想要做什么,你会如何在React中编写这个组件?

1 个答案:

答案 0 :(得分:0)

您应该在提出请求之前等待特定时间。这主要是延迟请求并等待用户输入。将您的onChange处理程序更改为此类

onChangeInternal = (event)=> {
    const jobId = event.target.value;
    this.props.onChange(jobId);
    clearTimeout(this.timeoutId); // resets the timeout on new input
    this.timeoutId = setTimeout(() => {
      this.loadDescription(jobId)
        .then((description)=> {
            this.setState({description});
        });
    }, 500); //delays request by 500ms. 

};

您还应该检查Lodash's Debounce.这会延迟函数调用一段时间。

希望这有帮助!