I am learning ReactJS. I would like to use functional component. In my component, I have a textbox and a clear button.
My concern is – whenever I type a char from my keyboard to enter info for the text box, I see the search account called!!!
in my console output. If i type 5 chars, I would see this 5 times – it basically means the whole component is re-rendered & methods re-defined.rt?
Is it not bad practice and affect the performance? Is there any other alternative?
import React, { useState, useContext } from 'react'; import AccountContext from . './accountContext' const SearchAccounts = () => { const [text, setText] = useState(''); const onChange = (evt) => setText(evt.target.value); console.log('search account called!!!'); // some methods are defined here onSubmit = () => {...} onClear = () => {...} return ( <div> <form onSubmit={onSubmit} className="form"> <input type="text" name="text" value={text} onChange={onChange} placeholder="Search Accounts..." /> <input type="submit" value="Search" className="...." /> </form> <button className="...." onClick={onClear} style={getClearStyle()} >Clear</button> </div> ); } export default SearchAccounts;
Advertisement
Answer
My concern is – whenever I type a char from my keyboard to enter info for the text box, I see the search account called!!! in my console output. If i type 5 chars, I would see this 5 times – it basically means the whole component is re-rendered & methods re-defined.rt?
Yes, this is expected and aligns with the mental model of React.
In React, you’ll hear people say “the view is a function of state” — meaning that whatever data you inside of variables in react state should directly determine the rendered output, sometimes refered to as “one-way data flow”
The consequence of doing this however is that, in order to determine what changed, you need to render the react component.
This is fine!
Remember what powers React — the virtual dom. Internally, react creates a light-weight representation of the browser’s DOM so that the above one-way data flow is efficient.
I see a separate concern here though regarding the amount of time you see the console.log
output.
What you’re doing there is a “side-effect” in React, and whenever you have a side-effect, you should wrap in in useEffect
. useEffect
will ensure your side-effect only runs when the values you feed to its dependency array changes.
const { useEffect, useState } = React; const { render } = ReactDOM function MyComponent() { const [value, setValue] = useState('world'); useEffect(() => { console.log('this should only render once'); }, []); useEffect(() => { console.log(`this will render on every value change: the value: ${value}`); }, [value]) return ( <label> hello, <input value={value} onChange={e => setValue(e.target.value)} /> </label> ); } render(<MyComponent />, document.querySelector('#root'));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <div id="root"></div>
See here for more on how useEffect
works and here if you want a deep dive.