I am updating some deprecated code in a react native app, and so I replaced this:
UNSAFE_componentWillReceiveProps(nextProps) {
if(
this.props.started != nextProps.started ||
this.props.stopped != nextProps.stopped ||
this.props.durationOverride != nextProps.durationOverride ||
this.props.editable != nextProps.editable
) {
this.loadTimer(nextProps);
}
}
... with this:
static async getDerivedStateFromProps(nextProps, props) {
if(
props.started != nextProps.started ||
props.stopped != nextProps.stopped ||
props.durationOverride != nextProps.durationOverride ||
props.editable != nextProps.editable
) {
await loadTimer(nextProps);
}
return null;
}
This works as expected, functionally. However, I am getting this yellow text message in the console:
[Unhandled promise rejection: ReferenceError: Can't find variable: loadTimer]
What is the issue here? Is it that I'm calling a function within getDerivedStateFromProps()
? Or is the issue that it's a promise? Or is the issue to do with the loadTimer()
function itself? That function looks like this:
async loadTimer(props) {
await Promise.all([
new Promise((resolve) => {
if(props.editable !== undefined) this.setState({
editable: props.editable,
}, resolve);
}),
new Promise((resolve) => {
if(props.stopped) {
this.setState({
stopTime: moment(props.stopped).format('YYYY-MM-DD HH:mm:ss'),
stopDuration: moment(props.stopped).format('HH:mm'),
}, resolve);
} else {
this.setState({
stopTime: null,
stopDuration: null,
}, resolve);
}
}),
new Promise((resolve) => {
if(props.stopTimeOffset && props.stopTimeOffset != Number.NaN) {
this.setState({ stopTimeOffset: props.stopTimeOffset }, resolve);
} else {
this.setState({ stopTimeOffset: 0 }, resolve);
}
}),
new Promise((resolve) => {
if(props.started) {
this.setState({
startTime: moment(props.started).format('YYYY-MM-DD HH:mm:ss'),
startDuration: moment(props.started).format('HH:mm'),
}, resolve);
} else {
this.setState({
startTime: null,
startDuration: null,
}, resolve);
}
})
]);
if(!props.stopped && props.started && this.state.editable) {
await this._startTimer();
} else {
if(props.durationOverride && !this.state.editable) {
this.setState({
duration: `${props.durationOverride}:00`,
durationShort: props.durationOverride,
});
} else {
const duration = this._getDuration();
this.setState({
duration: duration.long,
shortDuration: duration.short,
});
}
}
}
CodePudding user response:
This isn't the kind of case that getDerivedStateFromProps
is designed for. I recommend you put your code in componentDidUpdate
instead:
async componentDidUpdate(prevProps) {
if(
this.props.started != prevProps.started ||
this.props.stopped != prevProps.stopped ||
this.props.durationOverride != prevProps.durationOverride ||
this.props.editable != prevProps.editable
) {
await this.loadTimer(this.props);
}
}
You may find the following article from the react team useful: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html