React input loses focus after each keystroke

react input loses focus when typing
react.js loses input focus on typing
react input lose focus event
react hooks input loses focus when typing
react-table input loses focus
react hooks input losing focus
react input onchange one character
react form input losing focus when typing

I have a search bar on my nav component. After each keystroke, the input loses focus and you have to re-click on it to type the next key.

Here is the input:

<input
    type="text"
    name="search"
    placeholder="Search"
    value={search}
    onChange={handleInputChange}
/>

Here is the handleInputChange function:

function handleInputChange(event) {
   event.preventDefault();
   let value = event.target.value;
   setSearch(value);
}

Here is the hook for setting the search:

const [search, setSearch] = useState("");

I've tried adding a key to the input, but that doesn't work. When I move the search input to a new component, that also doesn't work.

Here is the complete code:

import React, { useEffect, useState, useCallback } from "react";
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import { Row, Col } from '../Grid';
import IconButton from '@material-ui/core/IconButton';
import SearchIcon from '@material-ui/icons/Search';
import ShoppingCartOutlinedIcon from '@material-ui/icons/ShoppingCartOutlined';
import MenuIcon from '@material-ui/icons/Menu';
import Badge from '@material-ui/core/Badge';
import useScrollTrigger from '@material-ui/core/useScrollTrigger';
import Slide from '@material-ui/core/Slide';
import SideMenu from '../SideMenu';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { css } from 'glamor';
import "./style.css";


function Navbar(props) {
    const cart = useSelector(state => state.cart);
    const [cartTotal, setCartTotal] = useState(0);
    const [loggedIn, setLoggedIn] = useState(false);
    const [search, setSearch] = useState("");
    const [isOpen, setIsOpen] = useState(false);
    const [renderMiddleCol, setMiddleCol] = useState(true);
    const [menuClass, setMenuClass] = useState("no-menu");

    useEffect(() => {
        if (cart[0]) {
            setCartTotal(cart[0].line_items.length)
        }
    }, [cart[0]]);
    useEffect(() => {
        if (window.sessionStorage.id) {
            setLoggedIn(true);
        } else {
            setLoggedIn(false);
        }
    }, [loggedIn]);
    useEffect(() => {
        if (window.innerWidth < 450) {
            setMiddleCol(false);
        } else {
            setMiddleCol(true);
        }
    }, [window.innerWidth]);
    function HideOnScroll(props) {
        const { children, window } = props;
        const trigger = useScrollTrigger({ target: window ? window() : undefined });
        return (
            <Slide appear={false} direction="down" in={!trigger}>
                {children}
            </Slide>
        );
    }
    HideOnScroll.propTypes = {
        children: PropTypes.element.isRequired,
        window: PropTypes.func,
    };
    function CheckCart() {
        if (window.sessionStorage.id) {
            window.location.href = "/cart";
        } else {
            toast("Please login to view your cart", {
                className: css({
                    background: '#3E0768',
                    boxShadow: '2px 2px 20px 2px rgba(0,0,0,0.3)',
                    borderRadius: '17px'
                }),
                bodyClassName: css({
                    fontSize: '20px',
                    color: 'white'
                }),
                progressClassName: css({
                    background: "linear-gradient(90deg, rgba(0,0,0,1) 0%, rgba(62,7,104,1) 80%)"
                })
            });
        }
    }
    function Search() {
        if (search) {
            sessionStorage.setItem("search", search);
            window.location.href = "/search";
        } else {
            toast("Search field cannot be empty", {
                className: css({
                    background: '#3E0768',
                    boxShadow: '2px 2px 20px 2px rgba(0,0,0,0.3)',
                    borderRadius: '17px'
                }),
                bodyClassName: css({
                    fontSize: '20px',
                    color: 'white'
                }),
                progressClassName: css({
                    background: "linear-gradient(90deg, rgba(0,0,0,1) 0%, rgba(62,7,104,1) 80%)"
                })
            });
        }
    }
    function logOut(event) {
        event.preventDefault();
        setIsOpen(false);
        sessionStorage.clear();
        window.location.href = "/login";
    }
    function handleInputChange(event) {
        event.preventDefault();
        let value = event.target.value;
        setSearch(value);
    }
    function toggleMenu(event) {
        event.preventDefault();
        setIsOpen(!isOpen);
        if (menuClass === "no-menu") {
            setMenuClass("menu-background");
        } else {
            setMenuClass("no-menu");
        }
    }
    const theme = createMuiTheme({
        palette: {
            primary: {
                main: '#000000',
                contrastText: '#ffffff',
            },
            secondary: {
                light: '#3E0768',
                main: '#3E0768',
                contrastText: '#ffffff',
            },
            tertiary: {
                main: '#ffffff',
            }
        },
    });

    return (
        <MuiThemeProvider theme={theme}>
            <HideOnScroll {...props}>
                <AppBar position="fixed" color="primary">
                    <Toolbar>
                        <Col size="md-1">
                            <IconButton
                                onClick={toggleMenu}
                                aria-label="Menu"
                            >
                                <MenuIcon
                                    fontSize="large"
                                    className="white"
                                />
                            </IconButton>
                        </Col>
                        <Col size="md-2">
                            <a href="/" className="white "><h6>Demo Company</h6></a>
                        </Col>
                        {renderMiddleCol ? (
                            <Col size="lg-6 md-5 sm-3" />
                        ) : (<div />)}
                        <Col size="md-2 4">
                            <Row no-gutters>
                                <div className="search-box">
                                    <Col size="md-2 1">
                                        <IconButton onClick={Search} aria-label="search" >
                                            <SearchIcon className="white" />
                                        </IconButton>
                                    </Col>
                                    <Col size="md-8 9">
                                        {/* <SearchForm
                                            value={search}
                                            onChange={handleInputChange}
                                        /> */}
                                        <input
                                            className="search-field white"
                                            type="text"
                                            name="search"
                                            placeholder="Search"
                                            value={search}
                                            onChange={handleInputChange}
                                        />
                                    </Col>
                                </div>
                            </Row>
                        </Col>
                        <Col size="md-1">
                            <IconButton
                                onClick={CheckCart}
                                aria-label="Go to cart"
                            >
                                <MuiThemeProvider theme={theme}>
                                    <Badge
                                        badgeContent={cartTotal}
                                        color="secondary"
                                    >
                                        <ShoppingCartOutlinedIcon className="white" />
                                    </Badge>
                                </MuiThemeProvider>
                            </IconButton>
                        </Col>
                    </Toolbar>
                </AppBar>
            </HideOnScroll>
            <SideMenu
                isOpen={isOpen}
                menuClass={menuClass}
                toggleMenu={toggleMenu}
                loggedIn={loggedIn}
                logOut={logOut}
            />
        </MuiThemeProvider>
    );
}

export default Navbar;

I ended up using a ref on the input and setting it focus on each re-render. Here is the code that fixed it.

const [search, setSearch] = useState("");
const searchInput = React.useRef(null);
useEffect(() => {
  searchInput.current.focus();
}, [search]);

And here is the input:

<input
  ref={searchInput}
  className="search-field white"
  type="text"
  name="search"
  placeholder="Search"
  value={search}
  onChange={handleInputChange}
/>

Credit for the solution: React: set focus on componentDidMount, how to do it with hooks?

React.js loses input focus on typing, Also, remember that such problem can be caused by invalid keys higher in the hierarchy. If the higher list component which contains all the recipient inputs used recipients. length as part of its key, then adding or removing recipients would cause losing focus as well. Then react re-rendered the page and updated the input. But because the key was different between re-renders it throws away the old input and adds a new input in its place. It looks identical, but it looses the focus. You should never use value as part of the key when users can edit the value.

I don't know exactly why, but my focus problem was solved by changing this code:

import { Route } from 'react-router-dom'
<Route path='xxx' component={() => <TheComponent... />}

where TheComponent contains the input element that loses focus while typing, to this code:

<Route path='xxx'>
  <TheComponent... />
</Route>

See my SO question, hopefully someone will soon shed some light on how this worked

Form input gets unfocused after typing in 1 character. � Issue #1853 , When I re-select it and continue typing it works normally. http://reactkungfu.com /2015/09/react-js-loses-input-focus-on-typing/ I managed to solve setState({ value: event.target.value });//update a state of the local componet� To get the input autofocus when the component is rendered, we call focus() on the textInput variable in the componentDidMount() method. Note that in order to access the DOM element of the ref we need to use the ref’s current property. React < 16.3. The example above uses React.createRef() API for creating refs. It was introduced in React 16.3.

Input loses focus after a single "keyDown" event � Issue #1557 , Definitely a noob at using Redux-form, so I probably should not jump in on the most cutting-edg Input loses focus after a single "keyDown" event #1557. Closed Semantic-Org/Semantic-UI-React#1370. Closed. @lock. In my component below, the input field loses focus after typing a character. While using Chrome's Inspector, it looks like the whole form is being re-rendered instead of just the value attribute of the input field when typing. I get no errors from either eslint nor Chrome Inspector.

React hooks, I am having the issue that the inputs lose focus after every key stroke, I'd assume because the component is re-rendering. The state of the form is initialised in the� As mentioned earlier, in React, onChange fires on each keystroke, not only on lost focus. On the other hand, onInput in React is a wrapper for the DOM’s onInput which fires on each change.

Input loses focus in React 15 : reactjs, [edit] SOLVED I'm having issues with an input element losing focus on re-renders when I type. I'm following a course which is teaching React 15.5.4 … MUI tracks the input value because the inner <input> element is used as a controlled component in order to detect empty/not-empty states. With regards to the redux-form issue, it looks like the input element loses and regains focus after each keystroke and I think that might be causing the cursor to jump to the end of the input.

Why my react component re-renders? | by David He, But it causes a problem that <AmountOwing /> input loses the focus when I start typing. In the first first place, I thought it might to do with� The input component is a wrapper to the HTML input element with custom styling and additional functionality. It accepts most of the same properties as the HTML input, but works great on desktop devices and integrates with the keyboard on mobile devices.

Comments
  • is your component re rendering in each keystroke? As it is setting state
  • post more code please
  • This codesanbox with the exact code you posted seems to not have the issue. More context might be needed. codesandbox.io/s/hopeful-cerf-iyt16
  • I edited the question with the complete code
  • @AsafAviv so if I need props, I cannot use input in the original code. I tried also to add id or key. But here, the main issue is if the original poster, I did not have a chance to study the entire code, can fix his/her problem with my hint. (Ooops, AsafAviv removed his comment)
  • Since I'm not mapping out multiple elements, I shouldn't need a key. And when I do add a key, it still loses focus.