Reputation: 6326
I am attempting to clean up my app and reduce the amount of re-renders that occur by using the React.memo
feature, however I am struggling to understand fully why my page/component is re-rendering the amount of times it is. I believe it is down to my Redux usage and the different reducer steps that hit (fire, success, error).
App.jsx (pseudocode)
console.log("App");
return <div>
<Switch>
...
<Route render={Home} />
...
</Switch>
</div>
export default App;
Home.jsx
const Home = () => {
console.log("Home");
return (
<div>
<DashboardBill/>
</div>
)
}
export default Home;
Dashboard.jsx
const Dashboard = () => {
console.log("Dashboard");
return <div>
<MyBill/>
</div>
}
export default memo(Dashboard);
MyBill.jsx
const mapStateToProps = ({billData}) => ({
billData
});
const mapDispatchToProps = (dispatch) => ({
loadData: () => dispatch(loadBillData)
});
const MyBill = ({billData, loadData}) => {
console.log("MyBill");
const [manipulatedData, setManipulatedData] = useState({});
useEffect(() => {
!billData && loadData();
}, []);
useEffect(() => {
billData && setManipulatedData(someUtil.manipulate(billData));
}, [billData]);
return <div>{manipulatedData}</div>;
}
export default connect(mapStateToProps, mapDispatchToProps)(memo(MyBill));
The dispatch
event ends up in a reducer that has the usual trigger, success and error cases to set the data within the Redux store etc.
When I load the page I am getting the following logging:
There are a few more dispatch
events within the main App.jsx going on, but only a couple so that could account for the extra App mentions in the logs.
Can somebody attempt to explain what is going on here and why my memo()
usages aren't doing what I am expecting?
Note: I am importing
memo
likeimport React, {memo, useEffect} from 'react';
Also, how would things be affected if MyBill
were to have children that themselves made Redux store changes?
Upvotes: 0
Views: 37
Reputation: 578
As I understand react.memo, render will be optimized if you use the component many times with the same props.
However, in your example, mapDispatchToProps provide a new function reference for loadData
on every render. So your component is never rendering with the same props.
I guess you can optimize one rendering using useMemo
hook
const MyBill = ({billData, loadData}) => {
const manipulatedData = useMemo(() => billData ? someUtil.manipulate(billData) : {}, [billData]);
useEffect(() => {
!billData && loadData();
}, []);
return <div>{manipulatedData}</div>;
}
Upvotes: 1