Why React Re-Renders

Why React Re-Renders

Discussion 1

Today, I will talk about some topics in React that should be considered for developing an optimized and scalable website in React.

Part 1: Re-rendering Issue

Consider the following code snippet:


const [showModal, setShowModal] = useState(false);

return (
 <div className={styles.column}>
 {showModal ? (
 <Modal
 show={showModal}
 handleClose={() => setShowModal(false)}
 />
 ) : null}

 <KanbanBoard />
 <Column />
 </div>
);
        

In this example, a modal is shown conditionally based on state changes. When the state changes, the whole component re-renders, regardless of how expensive other components might be. You might think of implementing a custom hook to handle this, like so:


const useModal = () => {
 const [isOpen, setIsOpen] = useState(false);

 return {
 isOpen,
 open: () => setIsOpen(true),
 close: () => setIsOpen(false),
 toggle: () => setIsOpen(!isOpen)
 };
};
Now, you use this in your component:

const { isOpen, toggle } = useModal();

return (
 <div className={styles.column}>
 {isOpen ? (
 <Modal
 show={isOpen}
 handleClose={toggle}
 />
 ) : null}

 <KanbanBoard />
 <Column />
 </div>
);

        

This will also cause re-renders because the state is still changing, which triggers a re-render. Although the state change is managed in the custom hook, it can still affect the component. Note that custom hooks can sometimes be dangerous because if you have a hook that records the screen size internally and you import that hook into other components, every state change will cause re-renders in those components.

Solution: The solution is to isolate the state changes of each component separately. For example:


const ModalWithButton = ({ title, todos, addTodo, moveTodo }) => {
 const [showModal, setShowModal] = useState(false);

 return (
 <div className={styles.column}>
 {showModal ? (
 <Modal
 show={showModal}
 handleClose={() => setShowModal(false)}
 />
 ) : null}

 <button onClick={() => setShowModal(true)}>Open Modal</button>
 </div>
 );
};

export default ModalWithButton;        

In the above component, you isolate the modal state completely in a different component and import this where you need it. Now, the state changes and re-rendering will only affect the ModalWithButton component, improving performance. This approach helps ensure that re-renders are confined to the specific component that requires state changes, reducing unnecessary re-renders and enhancing overall performance.


Hajime Yamasaki Vukelic

Software engineer | Frontend | Fullstack | Web Accessibility | I help teams that wish to build frustration-free UI

8 个月

One easy way to suppress *unnecessary* re-renders in the example you gave is to change the design to be fully event-driven without storing the modal dialog state anywhere. To do this you will need to make the following changes: 1. Change the modal implementation to use a <dialog> element. 2. Change the button's click handler so it doesn't update the state, but calls showModal() on the dialog element. 3. Change the modal's close button click handler to call close() on the dialog element. Since, in your case, the button that opens the modal isn't located in the same component as the <dialog> you can use a (global) event bus to establish communication between the button and the dialog. The window object is already an event bus, so that shouldn't be too hard. Imo, the modal should be a <dialog> element anyway, so I think this solution is a natural consequence of making the modal component use it.

要查看或添加评论,请登录

GOLAM KIBRIA ANIK的更多文章

社区洞察

其他会员也浏览了