The problem: I have a Parent component that has multiple buttons. Each button will fetch data from the API for different endpoints. The requirement is when a button is clicked it should go into a loading state and the other buttons should be disabled till the call completes.
What I have tried: I created two separate button components <Button1>
and <Button2>
which have their own isLoading
state. I have declared a disabled
state in the Parent component and I am passing this and its set handler down as props to the child button components. When the onClick
function is hit I set the isLoading
state to true and the setDisabled
property to true notifying the parent component about it. I have written the logic for the disabled
attribute on each child button component as diabled={!isLoading && disabled}
which means that the button will be disabled if it is not the one making the API call/loading.
Adding the code sandbox for this approach’s implementation and the one needed: https://codesandbox.io/s/sharp-hill-r4rsk0?file=/src/App.js
Solution support required: I need a way to reduce code duplication by using one single <Button>
component instead of multiple button components as a child in parent multiple times but don’t know how to separate their isLoading
, disabled
, and onClick
states and handlers when either of them is clicked and it should work as in the approach 1 as seen in the sandbox above.
2
Answers
React allows you to keep multiple instances of the same component by passing different props. It automatically manages the different states of each instance. So the same approach that you are currently using with different button components can be used with single button component.
Here the modified codesandbox having single button component with multiple instances.
The button component is as follows.
when the function
onSubmit
is called on click, it will change theisLoading
state of only that particular button instance totrue
. Other instances of this component will still haveisLoading
states as false. Thedisabled
state is being maintained in the parent component. So this state will be same for all the button instances. As we are applying disabled state asdisabled={!isLoading && disabled}
, the current clicked button will not be disabled becauseisLoading
will betrue
in this instance.Please check whether my code meets your requirement.
I have coded in the same file but you can make a separate file, also make sure to change the network Network throttling to Slow 3G or something to see the functionality clearly.
demo: https://codesandbox.io/s/cranky-shannon-vtwmz8?file=/src/App.js