user3106579
user3106579

Reputation: 663

prevent useEffect to fire on initial render

I want to do a debounce for custom input, but my problem is I can't stop useEffect from trigger on initial render

import { useDebouncedCallback } from "use-debounce";

interface myInputProps {
  getValue: any;
}

const MyInput = ({ getValue }: myInputProps) => {
  const [value, setValue] = useState("");

  React.useEffect(() => {
    getValue(value);
  }, [value]);

  return (
    <input type="text" value={value} onChange={e => setValue(e.target.value)} />
  );
};

export default function App() {
  const [debouncedCallback] = useDebouncedCallback(value => {
    console.log(value);
  }, 1000);

  return (
    <div className="App">
      <MyInput getValue={debouncedCallback} />
    </div>
  );
}

https://codesandbox.io/s/upbeat-lamport-ukq70?file=/src/App.tsx

I've also tried useLayoutEffect but it doesn't solve the problem.

Upvotes: 3

Views: 2352

Answers (2)

xdeepakv
xdeepakv

Reputation: 8135

Set initial value to undefined and you can explicitly check for undefined. Once the user enter, it won't be undefined.

const MyInput = ({ getValue }: myInputProps) => {
  const [value, setValue] = useState(undefined);
  React.useEffect(() => {
   if (value === undefined) {
      return;
    }
    getValue(value);
  }, [value]);

  return (
    <input type="text" value={value} onChange={e => setValue(e.target.value)} />
  );
};

Upvotes: 0

joy08
joy08

Reputation: 9662

We could use useRef to keep track of if it's the first time the useEffect hook is being run.

https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables

Sandbox link: https://codesandbox.io/s/confident-cerf-flkf2?file=/src/App.tsx


const MyInput = ({ getValue }: myInputProps) => {
  const [value, setValue] = useState("");
  const first = useRef(true);

  React.useEffect(() => {
    if (first.current) {
      first.current = false;
      return;
    }
    getValue(value);
  }, [value]);

  return (
    <input type="text" value={value} onChange={e => setValue(e.target.value)} />
  );
};

Upvotes: 4

Related Questions