最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - useEffect makes onChange and typing lagslow - Stack Overflow

programmeradmin1浏览0评论

I am creating a website where the user can type what he is looking for in a search bar.

Initially, I had a problem with the fact that onChange was one character behind the user search. For example, if the user search for "banana", the search was "banan". I understood that the problem es form the fact that setState is asynchronous. onChange is one character on delay - Hooks

To avoid this problem, I introduced the useEffect ponent in my code. It works. However now, if the user types some words, the words he types are not displayed immediately inside the search bar. They are displayed after few moments, as if it were a delay between what the user types and what it is displayed.

My searchbar ponent

export default function SearchBar({handlerSearchBar}) {
    const classes = useStyles();
    const [searchBarQuery, setSearchBarQuery] = React.useState([""])


    function handleChange(event) {
        setSearchBarQuery(event.target.value);
        console.log(searchBarQuery)
    }

    useEffect(() => {
        console.log("Search message inside useEffect: ", searchBarQuery);
        handlerSearchBar(searchBarQuery)
    });

    return (
        <form className={classes.container} noValidate autoComplete="off">
            <TextField
                required
                id="standard-full-width"
                label="Searchbar"
                style={{ marginLeft: 40, marginRight: 40 }}
                placeholder="Write your query"
                // helperText="The results will appear below!"
                fullWidth
                margin="normal"
                InputLabelProps={{
                    shrink: true,

                }}
                onChange={handleChange}
            />
        </form>
    );
}

handlerSearchBar function

It a function that is passing the results from my search-bar ponent to its parents and then, to its grandparents (SearchForm).

The grandparents SearchForm is setting one of its state to what is passed via the searchbar handlerSearchBar function:

function SearchForm() {
    const [searchBarQueryParent, setSearchBarQueryParent] = React.useState([""])

    function handlerSearchBar(searchBarQuery) {
        setSearchBarQueryParent(searchBarQuery)
        console.log(searchBarQuery)
    }
    return (something)
}

My question is: why is the display of the search words so much delayed than the their actual typing?

I think what is happening is that useEffect is called for each key stroke, and that is what it is so slow. I tried to call useEffect on onSubmit but there is no improvement.

Or it is my handlerSearchBar function that makes everything slow

I am creating a website where the user can type what he is looking for in a search bar.

Initially, I had a problem with the fact that onChange was one character behind the user search. For example, if the user search for "banana", the search was "banan". I understood that the problem es form the fact that setState is asynchronous. onChange is one character on delay - Hooks

To avoid this problem, I introduced the useEffect ponent in my code. It works. However now, if the user types some words, the words he types are not displayed immediately inside the search bar. They are displayed after few moments, as if it were a delay between what the user types and what it is displayed.

My searchbar ponent

export default function SearchBar({handlerSearchBar}) {
    const classes = useStyles();
    const [searchBarQuery, setSearchBarQuery] = React.useState([""])


    function handleChange(event) {
        setSearchBarQuery(event.target.value);
        console.log(searchBarQuery)
    }

    useEffect(() => {
        console.log("Search message inside useEffect: ", searchBarQuery);
        handlerSearchBar(searchBarQuery)
    });

    return (
        <form className={classes.container} noValidate autoComplete="off">
            <TextField
                required
                id="standard-full-width"
                label="Searchbar"
                style={{ marginLeft: 40, marginRight: 40 }}
                placeholder="Write your query"
                // helperText="The results will appear below!"
                fullWidth
                margin="normal"
                InputLabelProps={{
                    shrink: true,

                }}
                onChange={handleChange}
            />
        </form>
    );
}

handlerSearchBar function

It a function that is passing the results from my search-bar ponent to its parents and then, to its grandparents (SearchForm).

The grandparents SearchForm is setting one of its state to what is passed via the searchbar handlerSearchBar function:

function SearchForm() {
    const [searchBarQueryParent, setSearchBarQueryParent] = React.useState([""])

    function handlerSearchBar(searchBarQuery) {
        setSearchBarQueryParent(searchBarQuery)
        console.log(searchBarQuery)
    }
    return (something)
}

My question is: why is the display of the search words so much delayed than the their actual typing?

I think what is happening is that useEffect is called for each key stroke, and that is what it is so slow. I tried to call useEffect on onSubmit but there is no improvement.

Or it is my handlerSearchBar function that makes everything slow

Share Improve this question edited Nov 17, 2019 at 17:42 Magofoco asked Nov 17, 2019 at 17:33 MagofocoMagofoco 5,4867 gold badges43 silver badges87 bronze badges 6
  • Just finished replication of your code in sandbox, and... it works fine, no visible lag at all. – lankovova Commented Nov 17, 2019 at 17:48
  • I start to think the issue is the function handlerSearchBar . If I ment it, there is no lag but without it I do not see how I can pass searchBarQuery to the grandparent – Magofoco Commented Nov 17, 2019 at 17:50
  • In your case you can lift up state from SearchBar to SearchFrom ponent, in other words make SearchBar "fully controlled". – lankovova Commented Nov 17, 2019 at 17:54
  • But again, I see no issue with your current implementation. It works good. Maybe the source of this problem is in other parts of application. – lankovova Commented Nov 17, 2019 at 17:56
  • If I ment out handlerSearchBar(searchBarQuery) there is no lag. But clearly, the props are not set to the grandparent SearchFrom if I mented handlerSearchBar(searchBarQuery) out. – Magofoco Commented Nov 17, 2019 at 18:00
 |  Show 1 more ment

3 Answers 3

Reset to default 3

I resolved it by changing from onChange to onBlur.

I am not totally sure why the change works, but it does work.

You might wanna try to make it so that the useEffect fires only when searchBarQuery has been updated. i.e. as a callback upon setSearchBarQuery. You might do;

//...
    useEffect(() => {
        console.log("Search message inside useEffect: ", searchBarQuery);
        handlerSearchBar(searchBarQuery)
    }, [searchBarQuery]);
// ...

Note the second argument, an array, in useEffect to make that only run when that item has changed.

I might be a bit late to the game here, but what I did was to use a debounce function. This will check the input values every 1 sec, and will remove the lag as well

import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash.debounce';
import { TextField } from '@material-ui';

function SomeComp(props) {
  const [myValue, setMyValue] = useState(null);
  const [fetchDataSwitch, setFetchDataSwitch] = useState(false);

  // Limit the number of requests sent
  const debouncedFetchData = debounce((cb) => {
    cb(!fetchDataSwitch);
  }, 1000);

  useEffect(() => {
    debouncedFetchData((res) => {
      setFetchDataSwitch(res);
    });
  }, [myValue]);

  useEffect(() => {
    // check if input Is valid
    // fire API request

    return () => {
      // Clean up
    };
  }, [fetchDataSwitch]);

  return (
    <TextField
      InputProps={{
        inputProps: { min: 0 }
      }}
      fullWidth
      placeholder={'Max transit time...'}
      type={'number'}
      value={myValue || ''}
      onChange={({ target }) => setMyValue(target.value)}
    />
  );
}

SomeComp.propTypes = {};

SomeComp.defaultProps = {};

export default SomeComp;
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

发布评论

评论列表(0)

  1. 暂无评论