React save the onChange value and set it to another object if the user doesn't type anything within one second

Viewed 49

So, I'm trying to do something for my component, because I don't want for it to be rendered many times on each input, but rather, when 1 second is passed without the user typing something, after that to set it, but I'm facing some problems and what I've build don't work, it resets the state and so, Idk.

Here is the component:

import { Item } from '../..';
import { WorkItemValidation } from '../../../../../utils/Validation';
import { Date, Input } from '../../../Shared';
import { Editor } from '../../..';
import { Items } from '../Components';
import { Container, Liner, Linerier } from './Components'
import { useState } from 'react';
import { Employment as Work } from '../../../../../utils/operations/Resume';
import { useEffect } from 'react';

const Employment: any = (props: any) => {
    const [call, setCall] = useState(false);
    const [editors, setEditors] = useState({});
    const [currentIndex, setCurrentIndex] = useState("");

    const handleDescription = (e: any, index: number) => {
        setCurrentIndex(index);
        setEditors( { ...editors, [index]: e } )
        setTimeout(() => setCall(true), 1000)
    }

    useEffect(() => {
        setInterval(() => {
            if (call === true) {
                Work.Description(props, currentIndex, editors[currentIndex])
                setCurrentIndex("")
                setCall(false)
            }
        }, 1000)
    }, [])


    return (
        <Container>
            <Items>
                {
                    props.resume.employmentHistory.positions.map(
                        (position: any, index: number) => {

                            return (
                                                     <Editor
                                            label="Description"
                                            value={position.description && position.description || ''}
                                            
                                            onChange={(e) => handleDescription(e, index)}
                                        />
                            )
                        }
                    )
                }
            </Items>
        </Container >
    )
}

export default Employment;

So to handle when user types, after 1 second if he didn't put anything to change the state with the function Work.Description.

1 Answers

This is called debouncing a function and you may do it like:

const App = () => {
  const [value, setValue] = React.useState();
  const timeoutRef = React.useRef();
  
  const debounce = (func, args, delay) => {
    if (timeoutRef.current) {
      // canceling the previous timeout so the callback won't fire if
      // the user presses another key before 1 second
      clearTimeout(timeoutRef.current);
    }
    timeoutRef.current = setTimeout(() => {
      // calling func here will debounce it
      func(args);
    }, delay)
  }
  
  const handleChange = (inputValue) => {
    setValue(inputValue);
  }

  console.log("App rendered");

  return (
   <React.Fragment>
    <input
      type="text"
      onChange={(e) => debounce(handleChange, e.target.value, 1000)}
    />
    <p>Debounced value: {value}</p>
   </React.Fragment>
  )
}


ReactDOM
  .createRoot(document.getElementById("root"))
  .render(<App />);
input {
  border: 1px solid black;
  font-size: 16px;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

Related