Reputation: 386
I'm new with React and try to do a simple login connecting with one API. The connection its working fine, so i want create a div when login is fail.
For example one div "Bad user or password" after alert("NOT LOGIN")
I read stackoverflow and react documentation but i have doubts because i want to manipulate the DOM outside the render.
For example this code:
render() {
var renderedOutput = arr.map(item => <div> {item} </div>)
return (
<div>
{renderedOutput}
</div>
);
}
something like this var. Maybe is a very beginner mistake, but im stuck. Thank for the help and sorry the issues.
import *;
class App extends Component {
handleSubmit = e => {
e.preventDefault();
const user = {
usuario: this.usuario.value,
contraseña: this.password.value
};
axios.post(`http://api`, user).then(res => {
this.setState({
data: res.data,
loading: true
});
if (Object.keys(res.data).length > 0) {
alert("LOGIN");
} else {
alert("NOT LOGIN");
}
console.log(res.data);
});
}
render() {
return (
<Container>
<Form onSubmit={this.handleSubmit}>
<Row>
<Col md="4"> </Col>{" "}
<Col md="4">
<Card>
<CardBody>
<FormGroup>
<InputGroup>
<InputGroupAddon addonType="append">
<InputGroupText>
<FontAwesomeIcon icon={faUser} />{" "}
</InputGroupText>{" "}
</InputGroupAddon>{" "}
<Input
placeholder="Usuario"
type="text"
innerRef={element => {
this.usuario = element;
}}
/>{" "}
</InputGroup>{" "}
</FormGroup>
<FormGroup>
<InputGroup>
<InputGroupAddon addonType="append">
<InputGroupText>
<FontAwesomeIcon icon={faKey} />{" "}
</InputGroupText>{" "}
</InputGroupAddon>{" "}
<Input
placeholder="Password"
type="password"
innerRef={element => {
this.password = element;
}}
/>{" "}
</InputGroup>{" "}
</FormGroup>
<Row>
<Col md="8"> </Col>{" "}
<Col md="4">
<Button color="success"> Login </Button>{" "}
</Col>{" "}
</Row>{" "}
</CardBody>{" "}
</Card>{" "}
</Col>{" "}
<Col md="4"> </Col>{" "}
</Row>{" "}
</Form>
</Container>
);
}
}
export default App;
Upvotes: 1
Views: 572
Reputation: 315
You need to set error information in state when you detect api failure, then in render function if error state is found you can render error message html accordingly. we can write any javascript in render before returning jsx.
import *;
class App extends Component {
state={
data: null,
loading: false,
errorMessage: ''
}
handleSubmit = e => {
e.preventDefault();
const user = {
usuario: this.usuario.value,
contraseña: this.password.value
};
axios.post(`http://api`, user).then(res => {
this.setState({
data: res.data,
loading: true
});
if (Object.keys(res.data).length > 0) {
alert("LOGIN");
this.setState({
errorMessage: ''
});
} else {
this.setState({
errorMessage: 'Bad Login details'
});
alert("NOT LOGIN");
}
console.log(res.data);
});
}
render() {
let errorMessageHtml;
if(this.state.errorMessage){
errorMessageHtml = <p>{this.state.errorMessage}</p>
}
return (
<Container>
<Form onSubmit={this.handleSubmit}>
<Row>
<Col md="4"> </Col>{" "}
<Col md="4">
<Card>
<CardBody>
<FormGroup>
<InputGroup>
<InputGroupAddon addonType="append">
<InputGroupText>
<FontAwesomeIcon icon={faUser} />{" "}
</InputGroupText>{" "}
</InputGroupAddon>{" "}
<Input
placeholder="Usuario"
type="text"
innerRef={element => {
this.usuario = element;
}}
/>{" "}
</InputGroup>{" "}
</FormGroup>
<FormGroup>
<InputGroup>
<InputGroupAddon addonType="append">
<InputGroupText>
<FontAwesomeIcon icon={faKey} />{" "}
</InputGroupText>{" "}
</InputGroupAddon>{" "}
<Input
placeholder="Password"
type="password"
innerRef={element => {
this.password = element;
}}
/>{" "}
</InputGroup>{" "}
</FormGroup>
<Row>
<Col md="8"> </Col>{" "}
<Col md="4">
<Button color="success"> Login </Button>{" "}
</Col>{" "}
</Row>{" "}
</CardBody>{" "}
</Card>{" "}
</Col>{" "}
<Col md="4"> </Col>{" "}
</Row>{" "}
{errorMessageHtml}
</Form>
</Container>
);
}
}
export default App;
Upvotes: 2
Reputation: 4346
You shouldn't have to do any manual DOM manipulations for this type of problem. The "correct" way of doing this would be updating state (setState
) once your async request is complete which would trigger a re-render. You can store errors if the request fails, and clear them if the request is successful (you would also probably navigate away from this page on a successful login, but that's outside the scope).
Here is a trivial working example that should demonstrate how you can conditionally render errors. (Since this is an example, it doesn't matter what you put in the form - click "Submit" to make a request which will 404 and update state with an error).
class Example extends React.Component {
constructor (props) {
super(props)
this.state = {errors: []}
}
setErrors = (...errors) => {
this.setState({errors})
}
submitForm = () => {
// intentionally return a 404 as an example
// change to false to mock a valid ajax request
const hasError = true
axios.get(`https://jsonplaceholder.typicode.com/${
hasError ? 'fake' : 'todos/1'}`)
.then(() => {
this.setErrors()
})
.catch(() => {
this.setErrors('Invalid Email Or Password')
})
}
render () {
return (
<div>
<div style={{color: 'red'}}>
{this.state.errors.map(e => <div>{e}</div>)}
</div>
<div><label>Email<input type="email" /></label></div>
<div><label>Password<input type="password" /></label></div>
<button type="button" onClick={this.submitForm}>Submit</button>
</div>
)
}
}
ReactDOM.render(<Example />, document.querySelector('#app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
<div id="app"></div>
Upvotes: 2