Technical Retrospective: State Management Hell with useEffect



This is a technical retrospective on the decisions made when developing different aspects of NodeFlair’s product when I was interning here. This is done to hopefully make better decisions down the road. In this case it was NodeFlair’s revamped onboarding form.

What did you do?

Essentially I implemented the second page of the revamped onboarding form. The logic was relatively complex to me and my experience with state management was mediocre at best. This resulted in several state management complications.

Firstly, I had to have a combined state for the page itself. I tried to fit it to what the backend requires by fitting the shape and format of the JSON state as what was given to me. That way I could just make the POST request to my backend endpoint immediately without changing my data too much.

Secondly, I had to make a few custom components although we used the materialUI React UI framework. This meant combining a few material UI components into one, such as a stepper component with plus and minus buttons at each side. This had to be tied to a bigger portion as the number of steppers rendered is dependent on a previous component and the selections made on that. We wanted to have local states for each component so that when one of the child component’s state is updated, the rerender is only triggered to the child component and not the entire page itself. This resulted in multiple local states that had to be synced up with each other, and this patchwork was done using useEffect. This resulted in unpredictable behavior as it was hard to keep track of when each state change and thus rerender was queued.

Thirdly, we tried to use multiple context providers to sync up the state as well. This added to an additional source of truth and made things more complicated especially when business logic and form validation had to come into play.

Ultimately this page had to be refactored to be simpler and more reliable.

What did you learn?

Shape of the data

I first learnt to fit the shape of the state data to the UI I am making, instead of purely accommodating the back end API request. This would make things more convenient for me to deal with when manipulating and updating the data with my state changes. Afterwards before sending it to the back end,

Source of truth

I also learnt to have only 1 main source of truth. This would drastically reduce the amount of headaches when having to sync multiple states to each other using useEffect. Instead what is said to be a good common practice would be to house the state in the parent component and pass the states and setState callback function as child props. Therefore this would definitely ensure that only the parent state is being changed.

Planning component structure

I also learnt to plan my component structure as well. Proper planning with the right shape of the data in mind would definitely help.

Would you do it again?


Low-balled on salary during Offer?

Join the smarter way. Discover upfront real salary data backed by payslips and offer letters.

Join the growing community of 800+ tech talents who have already submitted their salary data. Put an end to salary opaqueness here in Singapore!

Follow us on Telegram (@nodeflairsg) for the latest Tech Insight, Reads, Salaries & Job Opportunities!

Related Articles