Having an issue firing this function if this.state.number
is equal to the numbers in the array.
delay = async () => {
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
await sleep(1000);
return <Redirect to="/dashboard" />
}
error
Invariant Violation: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
Home.js
import React, {Component} from 'react';
import {Redirect} from "react-router-dom";
import Grid from '@material-ui/core/Grid';
import './App.css';
import { withRouter } from 'react-router-dom'
class Home extends Component {
state = {
number: "",
numbers: ["111-111-1112, 111-111-1111, 111-111-1116, 111-111-1118"]
};
onChange = e => {
e.preventDefault();
this.setState({
number: e.target.value
});
};
delay = async () => {
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
await sleep(1000);
return <Redirect to="/dashboard" />
}
validate = myNum => this.state.numbers.find(num => num === myNum);
render(){
const validatedNumber = (
<div>
<span style={{ color: "green" }}>Activated ✅ </span>
{this.delay()}
</div>
);
return (
<div className="main">
<Grid container >
<Grid item sm={8} md={12} >
<input
type="text"
placeholder="Validate Number"
value={this.state.number}
onChange={this.onChange}
/>
<h2>
{this.validate(this.state.number) ? (
validatedNumber
) : (
<div>Not in the system</div>
)}
</h2>
</Grid>
</Grid>
</div>
);
}
}
export default Home;
You are getting this error beucase this.delay()
will return a Promise
object and you can't render objects.
Any function that have async
returns a Promise
.
To solve this, you need a if
to decide what to return and a state to keep the status
of the setTimeout
.
Keep a state of shouldRedirect
state = {
...
shouldRedirect: false
}
Update the state when the setTimeout
finishes
delay = async () => {
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
await sleep(1000);
this.setState({shouldRedirect: true})
}
Check in the render method if shouldRedirect
render(){
if(this.state.shouldRedirect){
return <Redirect to="/dashboard" />
}
// continue with normal render
...
}
Call delay
in the correct place
onChange = e => {
e.preventDefault();
let number = e.target.value
this.setState({number});
if(this.state.numbers.find(num => num === number)){
this.delay()
}
};
You have to capture the value of the event before passing it to setState
or else the event might go out of scope before state is set.
import React, {Component} from 'react';
import {Redirect} from "react-router-dom";
import Grid from '@material-ui/core/Grid';
import './App.css';
import { withRouter } from 'react-router-dom'
class Home extends Component {
state = {
number: "",
numbers: ["111-111-1112, 111-111-1111, 111-111-1116, 111-111-1118"],
isValid: false
};
onChange = e => {
const number = e.target.value
this.setState({ number });
if (this.isValid(number)) {
setTimeout(() => this.props.history.push('/dashboard'), 1000)
this.setState({ isValid: true })
}
};
isValid = myNum => this.state.numbers.find(num => num === myNum);
render() {
const { number, isValid } = this.state
return (
<div className="main">
<Grid container >
<Grid item sm={8} md={12} >
<input
type="text"
placeholder="Validate Number"
value={number}
onChange={this.onChange}
/>
<h2>
{isValid ? (
<div>
<span style={{ color: "green" }}>Activated ✅ </span>
</div>
)
: (
<div>Not in the system</div>
)}
</h2>
</Grid>
</Grid>
</div>
);
}
}
export default withRouter(Home);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With