My javascript/react skills are not great and the project is one that I’m adding onto someone else’s work.
I’m trying to create a reusable component being a button that:
- Disables immediately on press
- Calls a function when pressed
- Re-enables once function has finished work
Being a re-usable component we would pass in the function to call when pressed.
Reason for this is the function doing work may take some time to complete and we want to let user know that the button is not able to be pressed again until finished.
This button will replace existing ordinary buttons in the app. I’ve got a component working to disable and call the function.
However I’m experiencing “Can’t perform a React state update on unmounted component”.
This happens when the button is acting as a submit and also navigates to a new page before "do work" has finished.
Igor Soloydenko’s answer on this question solves the react state update - Can't perform a React state update on an unmounted component
I’m lost trying to convert this code into some kind of re-useable component.
Existing code I’ve got which does not implement Igor’s code below. How can I get this or similar to work similar to Igor ?
Class BaseButton:
import React from 'react';
export default class BaseButton extends React.Component {
constructor(props) {
super(props);
this.state = {
// You can set the button to be disabled initially.
disabled: props.disabled,
// This function that is called.
customOnPress: props.onPress,
};
}
/**
* Used to disable button when clicked.
*/
onPressWrapper = async () => {
// Disabled.
if (this.state.disabled) return;
this.setState({ disabled: true });
if (this.state.customOnPress != null) {
await this.state.customOnPress();
}
this.setState({ disabled: false });
};
// If the handler needs to be replaced without a parent re-render.
setNewOnPress = async (inPress) => (this.state.customOnPress = inPress);
// Disable without re-render from parent.
setDisabled = async (isDisabled) => (this.state.disabled = isDisabled);
}
Class ButtonWithDisable:
import React from 'react';
import BaseButton from './BaseButton';
import { Fa, InputHolder, Text, TextInput } from './ButtonStyles';
class ButtonWithDisable extends BaseButton {
constructor(props) {
super(props);
}
render() {
this.props.onPress = () => this.onPressWrapper();
return (
<InputHolder {...this.props} disabled={this.state.disabled}>
<TextInput {...this.props}>
{this.props.fa ? <Fa name={this.props.fa} {...this.props} children={undefined} /> : null}
{this.props.icon ? this.props.icon : null}
<Text {...this.props}>{this.props.children}</Text>
</TextInput>
</InputHolder>
);
}
}
export default ButtonWithDisable;
Example usage:
<ButtonWithDisable primary fa="check" small onPress={this.onSubmit}>
Submit
</ButtonWithDisable>