0

I've been trying to find a way to use useEffect like this, but I don't think I'm doing it properly:

const [searching, setSearching] = useState(false);
function OnSearch(e) {
        const searchValue = e.target.value;
        useEffect(() => {
            setSearching(true);
        }, []);
        clearTimeout(timer);
        timer = setTimeout(() => {
            setSearching(false);
            window.location.href = '/block/' + searchValue;
        }, 2000);
    }

Any kind of help or direction will be appreciated.

4
  • 1
    You don't need useEffect at this specific position. Just delete it and keep setSearching(true); and it works as you expect. Commented Jun 16, 2020 at 10:51
  • I tried that @MaiKaY but it actually seems break the searchValue redirect. If I type more than one character for searchValue, it strips it to 1 character. Commented Jun 16, 2020 at 10:55
  • See screencast here @MaiKaY share.getcloudapp.com/yAuY2NkP Commented Jun 16, 2020 at 10:56
  • To help you solve that problem, we'll need to have a minimal reproducible example demonstrating the problem, preferably a runnable one using Stack Snippets (the [<>] toolbar button). Stack Snippets support React, including JSX; here's how to do one. (Although I may have inadvertently fixed it by showing how to use non-state instance data in my answer.) Commented Jun 16, 2020 at 10:58

1 Answer 1

1

I assume from the useState you've used there that this code is inside a functional component. You don't need or want useEffect there, just remove it and do setSearching(true) directly:

const [searching, setSearching] = useState(false);
function OnSearch(e) {
    const searchValue = e.target.value;
    setSearching(true);
    clearTimeout(timer);
    timer = setTimeout(() => {
        setSearching(false);
        window.location.href = '/block/' + searchValue;
    }, 2000);
}

(In fact, not only do you not need it, but you can't use hooks anywhere other than the top level of a component function or hook function. So not in an event handler.)

That leaves the question of the timer variable. It can't just be a local variable in the component function because that will get recreated on every render. For non-state instance data like that, you can use an object via useRef, then use properties on that object, which will be consistent for the lifetime of the component:

const [instance] = useRef({});

So that gives us:

const [instance] = useRef({});
const [searching, setSearching] = useState(false);
function OnSearch(e) {
    const searchValue = e.target.value;
    setSearching(true);
    clearTimeout(instance.timer);
    instance.timer = setTimeout(() => {
        setSearching(false);
        window.location.href = '/block/' + searchValue;
    }, 2000);
}

Side note: In JavaScript, the overwhelmingly-common convention is that only constructor functions and (in React) component functions are capitalized, not other kinds of functions. So onSearch rather than OnSearch. You can do what you like in your own code of course, but when working with others or asking for help, sticking to conventions helps keep communication clear.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for explaining but my issue was fixed by adding in methods for onKeyUp and onKeyPress.
@designtocode - I'm glad you fixed the issue. I assume you also stopped using useEffect in OnSearch...? Because if it's an event callback, you don't use useEffect there.
Yep I renamed it to handleKeyUp and just used setSearching(true) and it works as expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.