I have a search query component. User types query, clicks run and executes it. However, due to how state is organized, it causes excessive re renders. Following is a simplification of it. This organization of the code feels natural to me. QueryEditor is normally a complex editor, hence it stores its own value. Similar for query results. I got the value of it on each change, updated the query in the parent component. However this causes all HTML elements in the parent component to re-render even though their state does not change.
First of all, not being very familiar with the concepts;
Is this expected behavior? What I've done might not be ideal, but causing every DOM elment to rerenders because parent state changed feels unncesseary to me. Or maybe I'm doing something wrong.
How would this be improved? Obviously thing to improve is not get every change as a callback, but I did not find a good way to call a method of child component to getValue() from a parent component.
Link if you want: https://codesandbox.io/s/purple-architecture-5kpx5?file=/src/App.tsx You can clearly see the performance impact with React DevTools and see the render time increases with the number of elements even the elements did not change but the query text changes.
function App() {
console.log("Re-render?");
const [name, setName] = useState("mustafa");
const [query, setQuery] = useState("");
const [data, setData] = useState<number[]>([]);
const runQuery = () => {
console.log("using query...", query);
setData([...Array(data.length + 1000).keys()]);
};
return (
<div>
<h1>Hello {name}</h1>
<p>Please enter your query</p>
<QueryEditor
onChange={(e) => {
setQuery(e.target.value);
}}
/>
<br />
<button onClick={runQuery}>Run Query</button>
<hr />
<h4>Results</h4>
{data.length > 0 && <p>There are {data.length} results </p>}
{data.length > 0 && <DataResults data={data} />}
</div>
);
}
interface EditorProps {
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
}
function QueryEditor({ onChange }: EditorProps) {
return <textarea onChange={onChange} />;
}
function DataResults({ data }: { data: number[] }) {
return (
<div>
<ul>
{data.map((a) => (
<li key={a}>Item {a}</li>
))}
</ul>
</div>
);
}