How i can use html <form> using redux? - javascript

I do not use html in form, because when I use and I click on <button type = "button" className = "button button2" onClick = {() => this.login ()}> logar </ button>, the page of a refresh and the error message some. But when I do not use it, this message appears to me in the console: [DOM] Password field is not contained in a form: (More info: https :// goo.gl/9p2vKq)
import React, {Component, Fragment} from 'react'
import {Redirect} from 'react-router-dom'
import { connect } from 'react-redux'
import ActionCreator from '../redux/actionCreators'
import styled from 'styled-components'
import Button from './elements/Button'
const BodyLogin = styled.div`
#formulario{
max-width: 850px
}`
import {Redirect} from 'react-router-dom'
class ScreensLogin extends Component {
constructor(props){
super(props)
this.state = {
form: {
email: '',
passwd: '',
}
}
}
componentDidMount(){
if (this.props.auth.error){
this.props.reset()
}
}
handleChange = field => event => {
const form = {
...this.state.form
}
form[field] = event.target.value
this.setState({form})
}
login = () => {
const {email, passwd} = this.state.form
this.props.login(email, passwd)
}
render(){
return (
<Fragment>
<BodyLogin>
<form> //this is my problem
<div className='form-group mx-auto' id="formulario">
<div className="input-group">
<div className="input-group-prepend">
<span className="input-group-text" id="">Email</span>
</div>
<input className="form-control" autoComplete='on' value={this.state.form.email} type="text" onChange={this.handleChange('email')} ></input>
</div>
<div className="input-group mt-5 mb-5">
<div className="input-group-prepend">
<span className="input-group-text" id="">Senha</span>
</div>
<input className="form-control" autoComplete='on' value={this.state.form.passwd} type="password" onChange={this.handleChange('passwd')} ></input>
</div>
<Button>
{<button type="button" className="button button2 " onClick={() => this.login()}>logar</button>}
</Button><br/><br/>
{this.props.auth.isAuth && <Redirect to={'/'}/>}
{
this.props.auth.error && <p className="text-danger">{this.props.auth.errorMessage}</p>
}
{
this.props.auth.isSigningin && <p className="text-info">Carregando...</p>
}
</div>
</form>
</BodyLogin>
</Fragment>
)
}
}
const mapStateToProps = state => {
return {
auth: state.auth
}
}
const mapDispatchToProps = dispatch => {
return {
login: (email, passwd) => dispatch(ActionCreator.signinRequest(email,passwd)),
reset: () => dispatch(ActionCreator.resetError())
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ScreensLogin)
Have some problem don't using the tag ?

You are using controlled component.
remove onclick from the button
<button type="button" className="button button2 " onClick={() => this.login()}>logar</button>
to
<button type="button" className="button button2">logar</button>
and in your form
<form onSubmit={this.login}>
this way you are actually submitting the form,
on other side you can pass event in button like this
<button type="button" className="button button2 " onClick={(e) => this.login(e)}>logar</button>
and in login function
login = (e) => {
e.preventDefault();
const {email, passwd} = this.state.form
this.props.login(email, passwd)
}
This way you can tell the form that I have handled submission of the form you do not need to do anything.

Related

What is v-if in react

What is v-if in react? I tried this but My div with loading class does not work when the loading data changes, so the div doesn't re-render itself.
codes is here:
{
loading &&
<div className="loading"></div>
}
I'm changing loading with a function, this function working with onclick event.
all of my code:
import React from "react";
import axios from "axios";
export class LoginPage extends React.Component{
render(){
let username = '',
password = '',
loading = false
function login(){
loading = true;
console.log(loading)
}
return (
<div className="App">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"
integrity="sha512-Fo3rlrZj/k7ujTnHg4CGR2D7kSs0v4LLanw2qksYuRlEzO+tcaEPQogQ0KaoGN26/zrn20ImR1DfuLWnOo7aBA=="
crossOrigin="anonymous" referrerpolicy="no-referrer"/>
{
loading &&
<div className="loading"></div>
}
<div className="login">
<h1>Login/Register</h1>
<div>
<i className="fas fa-user"></i>
<input type="text" onChange={(e) => username = e.target.value} placeholder="Username" maxLength="15"/>
</div>
<div>
<i className="fas fa-lock"></i>
<input type="Password" placeholder="Password" onChange={(e) => password = e.target.value} maxLength="18"/>
</div>
<button onClick={() => login()}>Login/Register</button>
</div>
</div>
);
}
}
I'd suggest you read about React State, some things in this piece of code are wrong. But let's fix your problem.
First add this variable to the state and then change it with setState, to trigger a rerender:
export class LoginPage extends React.Component{
constructor(props) {
super(props);
this.state = {
loading: false
};
}
login(){
this.setState({ loading: true })
console.log(this.state.loading)
}
render(){
let username = '',
password = '',
// your return will stay the same
}
}

How to get a variable back from a called component

I have a problem: I have my main class Input.js. A user can select a photo and upload it. The problem is I want to check if the user uploaded a photo or not when he press the button. For example I can give from Profilepic.js to Pic.js the picture as props. But how could I get back a variable? For example I want to set the variable in Profilepic.js and when the user I pressing the button the method onClick() should executed. Inside of this method it should check which value the variable isPreview has. And if the User hasnt uploaded a picture there should be a lable signaling him that he has to upload an image to continue.
Input.js
import React, { useState, useEffect } from 'react';
import { InputTags } from 'react-bootstrap-tagsinput';
import 'react-bootstrap-tagsinput/dist/index.css';
import './Input.css';
import Profilepic from './Profilepic';
const Input = () => {
const checkAll = () => {
// Call Preview from Profilepic.js
}
return (
<div className="body-container">
<Profilepic></Profilepic>
<div className="row gutters">
<div className="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-12">
<div className="text-right">
<button type="button" id="submit" name="submit" className="btn btn-primary" onClick={checkAll}>Speichern & Weiter <i class="fas fa-paper-plane"></i></button>
</div>
</div>
</div>
</div>
);
}
export default Input
Profilepic.js
import React, { useState } from "react";
import { Pic } from "./Pic.js";
const Profilpic = () => {
const [preview, setPreview] = useState(null);
const [isPreview, setIsPreview] = useState(false);
const fileSelectedHandler = (event) => {
try {
console.log(event.target.files[0]);
if (event.target.files[0].size > 70001680) {
alert("File is too big! Wie Samys Dick");
} else {
let img = URL.createObjectURL(event.target.files[0]);
setPreview(img);
setIsPreview(true);
}
}
catch (err) {
}
};
return (
<div>
{preview ? (
<div>
<label htmlFor="myInput">
<Pic preview={preview}></Pic>
</label>
<input
id="myInput"
style={{ display: "none" }}
type={"file"}
onChange={fileSelectedHandler}
/>
</div>
) : (
<div>
<label htmlFor="myInput">
<i className="fas fa-user-circle"></i>
</label>
<input
id="myInput"
style={{ display: "none" }}
type={"file"}
accept=".png,.jpg,.jpeg, .jfif"
onChange={fileSelectedHandler}
/>
</div>
)}
</div>
);
};
export default Profilpic;
Pic.js
import React from "react";
import "./Photo.css";
const STYLES = ["btn--primary", "btn--outline", "btn--test"];
const SIZES = ["btn--medium", "btn--large"];
export const Pic = ({ preview }) => {
//const checkButtonStyle = STYLES.includes(buttonStyle) ? buttonStyle : STYLES[0];
//const checkButtonSize = SIZES.includes(buttonSize) ? buttonSize : SIZES[0];
// Püsh for Samy
return (
<div class="profilepic">
<img
class="profilepic__image"
src={preview}
width="120"
height="120"
alt="Profibild"
/>
<div class="profilepic__content">
<span class="profilepic__icon">
<i class="fas fa-camera"></i>
</span>
<span class="profilepic__text">Profilbild ändern</span>
</div>
</div>
);
};
Description of the Problem
You can use the useImperativeHandle. This requires a bit of a wrapping of
Profilepic
import React, { forwardRef, useImperativeHandle, useState } from "react";
import { Pic } from "./Pic.js";
function Profilepic(props, ref) {
const [preview, setPreview] = useState(null);
const [isPreview, setIsPreview] = useState(false);
useImperativeHandle(
ref,
() => ({ isPreview }),
[isPreview]
);
...
return (
...
);
};
export default forwardRef(Profilepic);
Input
import React, { useState, useEffect, useRef } from 'react';
import Profilepic from './Profilepic';
const Input = () => {
const profilePicRef = useRef();
const checkAll = () => {
// access profilePicRef.current.isPreview
}
return (
<div className="body-container">
<Profilepic ref={profilePicRef} />
...
<button
type="button"
id="submit"
name="submit"
className="btn btn-primary"
onClick={checkAll}
>
Speichern & Weiter <i class="fas fa-paper-plane" />
</button>
...
</div>
);
}

this.props.history is not redirecting to homepage

I'm trying to redirect the user back to the index page, when a user clicks handleSubmit. However the data gets sent to the backend, but stays on the page with the user information still keyed in.
It does not render an error.
Here is the demo.
https://stackblitz.com/edit/react-h9ekc4
Navbar
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import SignUp from './SignUp';
import SignIn from './SignIn';
const Navbar = () => {
return(
<Router>
<div>
<nav className="navbar navbar-expand-lg navbar-light bg-light ">
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExample08" aria-controls="navbarsExample08" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse justify-content-md-center" id="navbarsExample08">
<ul className="navbar-nav">
<li className="nav-item">
<Link className="nav-link" to="/SignUp">Sign Up </Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/SignIn">Sign In </Link>
</li>
</ul>
</div>
</nav>
<Route path="/SignUp" component={SignUp} />
<Route path="/SignIn" component={SignIn} />
</div>
</Router>
);
}
export default Navbar;
SignUp.js
import React, {Component} from 'react';
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import {signUp ,onEmailSignUpChangeAction,onPasswordSignUpChangeAction} from '../actions/';
class SignUp extends Component {
state = {
email: "",
password: ""
}
// onChange = (e) =>{
// this.setState({
// [e.target.name] : e.target.value
// })
// }
handleSubmit = (e) =>{
e.preventDefault();
const register = this.props.signUp();
// this.props.history not working
(register === true) && this.props.history.push('/');
console.log(this.state);
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<h1>Sign Up</h1>
<div>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email address</label>
<input
type="email"
className="form-control"
id="email"
onChange={this.props.onEmailSignUpChangeAction}
aria-describedby="emailHelp"
value={this.props.emailSignUp}
placeholder="Enter email"/>
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div className="form-group">
<label htmlFor="exampleInputPassword1">Password</label>
<input
type="password"
className="form-control"
id="password"
value={this.props.passwordSignUp}
onChange={this.props.onPasswordSignUpChangeAction}
placeholder="Password"/>
</div>
<button type="submit" onClick={this.handleSubmit} className="btn btn-primary">Submit</button>
</div>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => ({
user: state.auth.user,
emailSignUp:state.signUpAuth.emailSignUp,
passwordSignUp:state.signUpAuth.passwordSignUp
})
const mapDispatchToProps = (dispatch) => ({
signUp: () => dispatch(signUp()),
onEmailSignUpChangeAction: (event) => dispatch(onEmailSignUpChangeAction(event.target.value)),
onPasswordSignUpChangeAction: (event) => dispatch(onPasswordSignUpChangeAction(event.target.value)),
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SignUp));
since your action signUp() is not returning anything.
register = this.props.signUp() is always undefined and hence the below line never executes..
(register === true) && this.props.history.push('/');
try returning true/false based on your logic and then try running your code again
Your dispatch call this.props.signUp() is returning undefined, hence this.props.history.push('/') is not executing.
just tried to add a console.log
handleSubmit = (e) =>{
e.preventDefault();
const register = this.props.signUp();
console.log(register);
(register === true) && this.props.history.push('/');
console.log(this.state);
}
register dispatch should be returning boolean.

How ReactJS display fetch response onClick

I am trying to generate a random user information when pressing the button, and display the information above the button. In ProfilePanel.js, I created a avatar and user constants, which will use to show the information. In index.js, the avatar constant works for that since it doesn't need to use the Button. however, for user constant, it doesn't work. In below's code, I am fetching a api data to display user name, but it didn't show anything, I am not sure where wrong, is something wrong in Button.js or index.js. and how can I fix it. Can somebody help me out? Thanks.
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
index.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import Panel from "./ProfilePanel";
import axios from 'axios';
import './index.css';
import Button from './Button';
const url = 'https://randomuser.me/api/';
class App extends Component {
constructor(props) {
super(props);
this.state = {
contacts: []
}
}
componentDidMount() {
this.fetchdata();
}
fetchdata() {
axios.get(url)
.then(res => {
console.log(res);
this.setState({ contacts: res.data.results});
});
}
render(){
const {contacts} = this.state;
return (
<div className="panel">
{contacts.map(contact => (
<div class="panel">
<Panel
key={contact.picture} avatar={contact.picture.medium}
/>
<li class="flex-container">
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
<Button title="location" onClick={this.fetchdata}>
</Button>
<Button key={contact.email} title="email">
</Button>
<Button key={contact.phone} title="phone">
</Button>
<Button key={contact.login.password} title="password">
</Button>
</li>
</div>
))}
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById("root")
);
ProfilePanel.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import './index.css';
import Button from './Button';
const style={
borderRadius: 150,
margin: 15,
}
class Panel extends Component {
render() {
const { avatar, user } = this.props;
return (
<div className="Panel">
<div class="panels">
<div className="avatar">
<img src={avatar} class="imageStyle" alt="" width={"200%"} height={"auto"}/>
</div>
</div>
<div class="center">
<h2 className="user">{user}</h2>
</div>
</div>
);
}
}
export default Panel;
Button.js
import './index.css';
import React, { Component } from 'react';
class Button extends Component {
constructor(props) {
super(props);
this.state = {
open:false,
};
}
render() {
const { title } = this.props;
const {open} = this.state;
return (
<button className={` ${open ? 'open' : ''}`}
class='button' onClick={(e) => this.handleClick(e)}>
<div className="panel-heading">
<h2 class='buttoncenter'>{title}</h2>
</div>
</button>
);
}
handleClick(e) {
e.preventDefault();
this.setState({
open: this.state.open
})
}
}
export default Button;
You're not changing state in the handle click. You need to set open to true;
handleClick(e) {
e.preventDefault();
this.setState({
open: true
})
}
You need to pass your user information in index.js. I think you have missed to pass the user props to the panel component, so that it shows the avatar alone. Without passing the users props, you are trying to destructure there in panel component.
//index.js should be like this
render(){
const {contacts} = this.state;
return (
<div className="panel">
{contacts.map(contact => (
<div class="panel">
<Panel
key={contact.picture} user={contact.name} avatar={contact.picture.medium}
/>
<li class="flex-container">
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
<Button title="location" onClick={this.fetchdata}>
</Button>
<Button key={contact.email} title="email">
</Button>
<Button key={contact.phone} title="phone">
</Button>
<Button key={contact.login.password} title="password">
</Button>
</li>
</div>
))}
</div>
);
}

React-Redux: Passing Event Handling inside map function

New to React/Redux, I am having hard time implementing on event handling.
I know that the 'this' reference key goes null when passed into the map (this.props.addRecipe.map of recipebox) function but I don't how to resolve it.
Essentially I would like to pass the onChange handler to ModalBox for each element in the array.
src/containers/recipebox
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ListGroup, ListGroupItem, Panel, Button, Modals } from 'react-bootstrap';
import MyModal from '../components/mymodal';
import { bindActionCreators } from 'redux';
import { deleteRecipe } from '../actions/index';
import shortid from 'shortid'
import ModalBox from '../containers/modalbox'
class RecipeBox extends Component {
constructor(props){
super(props);
this.renderRecipeList = this.renderRecipeList.bind(this)
this.handleRecipeNameChange = this.handleRecipeNameChange.bind(this)
this.handleUserIngredientsChange = this.handleUserIngredientsChange.bind(this)
}
handleRecipeNameChange(event){
this.setState({recipeName: event.target.value})
}
handleUserIngredientsChange(event){
this.setState({userIngredients: event.target.value})
}
renderRecipeList(recipeItem, index){
const recipe = recipeItem.recipe;
const ingredients = recipeItem.ingredients;
const id = shortid.generate();
return(
<div key={id}>
<Panel bsStyle="primary" collapsible header={<h3>{recipe}</h3>}>
<ListGroup >
<ListGroupItem header="Ingredients"></ListGroupItem>
{ingredients.map(function(ingredient,index){
return <ListGroupItem key={index}>{ingredient}</ListGroupItem>;
})}
<ListGroupItem>
<Button
onClick={() => this.props.deleteRecipe(recipeItem)}
bsStyle="danger">Delete
</Button>
<ModalBox
modalTextTitle={'Edit Recipe'}
recipeName={recipe}
userIngredients={ingredients}
handleRecipeNameChange={this.handleRecipeNameChange}
handleUserIngredientsChange={this.handleUserIngredientsChange}
onClickSubmit={this.onClickSubmit}
/>
</ListGroupItem>
</ListGroup>
</Panel>
</div>
)
}
render(){
return(
<div className="container">
<div className='panel-group'>
{this.props.addRecipe.map(this.renderRecipeList)}
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
addRecipe : state.recipeState
};
}
function mapDispatchToProps(dispatch){
return bindActionCreators({deleteRecipe : deleteRecipe}, dispatch)
}
export default connect(mapStateToProps,mapDispatchToProps)(RecipeBox);
src/containers/modalbox
import React, { Component } from 'react';
import { Button, Modal } from 'react-bootstrap';
class ModalBox extends Component {
constructor(props){
super(props)
this.state = {
showModal: false
};
this.toggleModal = this.toggleModal.bind(this);
}
toggleModal(){
this.setState({
showModal: !this.state.showModal
});
}
submitData(link){
link()
this.toggleModal()
}
render() {
return (
<div>
<Button
bsStyle="info"
onClick={this.toggleModal}
>
{this.props.modalTextTitle}
</Button>
<Modal show={this.state.showModal} onHide={this.toggleModal}>
<Modal.Header closeButton>
<Modal.Title>{this.props.modalTextTitle}</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<div className="form-group">
<label htmlFor="recipeName">Name of Recipe:</label>
<input
value={this.props.recipeName}
onChange= {this.props.handleRecipeNameChange}
type="text"
className="form-control"
id="recipeName" />
</div>
<div className="form-group">
<label htmlFor="userIngredients">Ingredients:</label>
<textarea
placeholder="you can seperate by comma"
value={this.props.userIngredients}
onChange={this.props.handleUserIngredientsChange}
type="text"
className="form-control"
id="userIngredients" />
</div>
</form>
</Modal.Body>
<Modal.Footer>
<Button
bsStyle="info"
onClick={ () => this.submitData(this.props.onClickSubmit) }>
{this.props.modalTextTitle}
</Button>
<Button
bsStyle="danger"
onClick= {this.toggleModal}
>Close</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
export default ModalBox
inside map function you need to change the this like below code,
render(){
const self = this;
return(
<div className="container">
<div className='panel-group'>
{this.props.addRecipe.map(self.renderRecipeList)}
</div>
</div>
)
}

Categories