简体   繁体   中英

Update a component with onChange. React-Hooks

I'm building a dropdown with suggestions that fetch data from an API. The input from the search bar is being stored using setState and it is updated when i change the value in the text input.

The thing is that I'm not managing to update the users lists from the dropdown each time I enter a new character in the text input. Can I somehow force the component to be rendered every time the props change? Or is there a better approach?

import React, {useState, useEffect} from 'react';
import Dropdown from '../Dropdown/Dropdown';
import './SearchBar.css';


// Component created with arrow function making use of hooks
const SearchBar = (props) => {

    const [input, setInput] = useState('');
    const [dropdownComponent, updateDropdown] = useState(<Dropdown input={input}/>)

    useEffect(() => {updateDropdown(<Dropdown input={input}/>)}, [input])

    const onChange = (e) => {
        setInput(e.currentTarget.value)
        updateDropdown(<Dropdown input={input}/>)
        console.log("=(")
    }



    return(
        <div className="search-bar">
            <input type="text" placeholder={props.placeholder} onChange={onChange}/>
            {dropdownComponent}
        </div>

    )
}

export default SearchBar;

I can't make the problem happen using your code in a simple test, but your onChange does has a problem: It's using input to update the dropdown, but it's not using useCallback to ensure that input isn't stale when it does. Either:

  1. Don't update the dropdown in your onChange , allowing your useEffect callback to do it; or

  2. Use e.target.value instead of input and get rid of the useEffect updating the dropdown; or

  3. Don't memoize the dropdown (eg, don't put it in state) since you want to update it when the input changes anyway, just render it directly in the JSX

Of those, with what you've shown, #3 is probably the simplest:

const SearchBar = (props) => {

    const [input, setInput] = useState('');

    const onChange = (e) => {
        setInput(e.currentTarget.value);
    };

    return(
        <div className="search-bar">
            <input type="text" placeholder={props.placeholder} onChange={onChange}/>
            <Dropdown input={input}/>
        </div>
    );
}

Live Example:

 const {useState, useEffect} = React; function Dropdown({input}) { return <div>Dropdown for "{input}"</div>; } const SearchBar = (props) => { const [input, setInput] = useState(''); const onChange = (e) => { setInput(e.currentTarget.value); }; return( <div className="search-bar"> <input type="text" placeholder={props.placeholder} onChange={onChange}/> <Dropdown input={input}/> </div> ); } ReactDOM.render(<SearchBar />, document.getElementById("root"));
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM