4
\$\begingroup\$

Following is my working application that contains a Search Container, a Sorting Container and a listing Container.

Based on Search and Sort the listing data changes in the listing container.

The application works fine though I noticed in my Search container whenever I am changing the input value in an input box, select component is re rendering and vice versa(check console).

Is there any pattern or modification I can do to minimise the re renders in the application ?

Working Demo - https://ojlrd.csb.app/

Codesandbox - https://codesandbox.io/s/rerender-ojlrd?file=/src/index.js


Code -

Page.js

const Page = () => {
 const [pageData, setPageData] = useState({
 search: {},
 sort: {
 sortBy: ''
 }
 });
 const getData = useCallback((type, data) => {
 setPageData(prevVal => {
 return {
 ...prevVal,
 [type]: {...data}
 }
 })
 }, [setPageData]);
 
 return (
 <div className="container">
 <SearchContainer getData={getData} />
 <SortingContainer getData={getData} />
 <ListingContainer urlData={pageData} />
 </div>
 );
};
export default Page;

SearchContainer.js

const SearchContainer = ({
 getData = () => {}
}) => {
 const [searchData, setSearchData] = useState({
 search1: '',
 search2: '13',
 search3: '',
 search4: '44'
 });
 useEffect(() => {
 getData('search', searchData);
 }, [searchData, getData]);
 const eventHandler = e => {
 setSearchData(prevVal => {
 return {
 ...prevVal,
 [e.target.name]: e.target.value
 }
 })
 }
 return (
 <div className="container-search">
 <h3>Search container</h3>
 <div className="container-search-actions">
 <Input
 initialValue=''
 label='Input 1'
 name="search1"
 eventHandler={eventHandler}
 />
 <Select
 label='Select 2'
 name="search2"
 options={[
 {label: 'Label 11', value: '11'},
 {label: 'Label 12', value: '12'},
 {label: 'Label 13', value: '13'},
 {label: 'Label 14', value: '14'}
 ]}
 selectedValue='13'
 eventHandler={eventHandler}
 />
 <Input
 initialValue=''
 label='Input 3'
 name="search3"
 eventHandler={eventHandler}
 />
 <Select
 label='Select 4'
 name="search4"
 options={[
 {label: 'Label 41', value: '41'},
 {label: 'Label 42', value: '42'},
 {label: 'Label 43', value: '43'},
 {label: 'Label 44', value: '44'}
 ]}
 selectedValue='44'
 eventHandler={eventHandler}
 />
 </div>
 </div>
 )
}
export default SearchContainer;

SortingContainer.js

const SortingContainer = ({
 getData = () => {}
}) => {
 const [sortData, setSortData] = useState({
 sortBy: 'desc'
 })
 useEffect(() => {
 getData('sort', sortData);
 }, [sortData, getData]);
 const eventHandler = e => {
 setSortData(prevVal => {
 return {
 ...prevVal,
 [e.target.name]: e.target.value
 }
 })
 }
 return (
 <div className="container-sorting">
 <Select 
 label='Sort By'
 name='sortBy'
 options={[
 {label: 'Ascending', value: 'asc'},
 {label: 'Descending', value: 'desc'}
 ]}
 selectedValue='desc'
 eventHandler={eventHandler}
 />
 </div>
 );
}
export default SortingContainer;

ListingContainer.js

const ListingContainer = ({ urlData }) => {
 const createURL = (urlData) => {
 const { search, sort } = urlData;
 let url = "/api?";
 [search, sort].forEach((element) => {
 for (const [key, value] of Object.entries(element)) {
 url += `&${key}=${value}`;
 }
 });
 return url;
 };
 return (
 <div className="container-listing">
 This is a listing container
 <p>URL Formed - </p>
 <p className="bold">{createURL(urlData)}</p>
 </div>
 );
};
export default ListingContainer;
asked Sep 23, 2021 at 22:35
\$\endgroup\$

1 Answer 1

3
+50
\$\begingroup\$

I was able to resolve this by adding a memo wrapper around the components' export statements, then passing in a compare function that returns true. The components were re-rendering each time the eventHandler function was re-created when the state of the parent changed on each input.

Since you pass no dynamic data in, there is no reason for these components to re-render except when their own state is updated.

See a working example here.

Input.js

...
export default memo(Input, () => true);

Select.js

...
export default memo(Select, () => true);

Source

Stephen Rauch
4,31412 gold badges24 silver badges36 bronze badges
answered Sep 26, 2021 at 17:02
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.