Component re run multiple times on setting state - javascript

I am trying to set my state in component did Mount lifecycle method in order to check the data I am getting from local storage and taking decision either to direct the user to the login page or keep remain the user on the dashboard if my local storage data exists in my local storage.
Or is there any way I can prevent switching the page to login on refreshing the web page and remain on the same even after reloading the browser if I have my data in local storage.
Thanks in advance!
import React, { Component } from "react";
import { Row, Col, Input, Button, Alert, Container, Label } from "reactstrap";
// Redux
import { connect } from "react-redux";
import { withRouter, Link, Route, Redirect } from "react-router-dom";
// availity-reactstrap-validation
import { AvForm, AvField } from "availity-reactstrap-validation";
// actions
import { checkLogin, apiError } from "../../store/actions";
import { loginAction } from "../../redux/actions/authActions";
// import images
import logodark from "../../assets/images/logo-dark.png";
import logolight from "../../assets/images/logo-light.png";
class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: "test#gmail.com",
password: "246810",
};
this.handleSubmit = this.handleSubmit.bind(this);
}
async handleSubmit(event, values) {
this.props.checkLogin(values, this.props.history);
const { username, password } = this.state;
localStorage.setItem("username", username);
localStorage.setItem("password", password);
let action = await this.props.loginAction(values, () => {
this.props.history.push({
pathname: "/dashboard",
});
});
}
// username = localStorage.getItem("username");
// password = localStorage.getItem("password");
// if (window.performance.getEntriesByType("navigation")[0].type).toSring() === 'back_forward') {
// window.location.reload()
// }
updateUser = (username, password) => {
this.setState({ username: username, password: password });
};
componentDidMount() {
// this.setState({
// // set username and password from local storage
// username: JSON.parse(localStorage.getItem("username")),
// password: JSON.parse(localStorage.getItem("password")),
// });
const username = localStorage.getItem("username");
const password = localStorage.getItem("password");
this.props.apiError("");
document.body.classList.add("auth-body-bg");
console.log("on page reload", window.performance.navigation);
if (window.performance.navigation.type !== 0) {
if (username && password) {
this.props.history.push({
pathname: "/dashboard",
});
} else {
this.props.history.push({
pathname: "/login",
});
}
}
}
componentWillUnmount() {
document.body.classList.remove("auth-body-bg");
}
render() {
return (
<React.Fragment>
<div>
<Container fluid className="p-0">
<Row className="g-0">
<Col lg={4}>
<div className="authentication-page-content p-4 d-flex align-items-center min-vh-100">
<div className="w-100">
<Row className="justify-content-center">
<Col lg={9}>
<div>
<div className="text-center">
<div>
<Link to="/" class="">
<img
src={logodark}
alt=""
height="20"
class="auth-logo logo-dark mx-auto"
/>
<img
src={logolight}
alt=""
height="20"
class="auth-logo logo-light mx-auto"
/>
</Link>
</div>
<h4 className="font-size-18 mt-4">
Welcome Back !
</h4>
{/* <p className="text-muted">Sign in to continue to Nazox.</p> */}
</div>
{/* {this.props.loginError && this.props.loginError ? <Alert color="danger">{this.props.loginError}</Alert> : null} */}
<div className="p-2 mt-5">
<AvForm
className="form-horizontal"
onValidSubmit={this.handleSubmit}
>
<div className="auth-form-group-custom mb-4">
<i className="ri-user-2-line auti-custom-input-icon"></i>
<Label htmlFor="username">Email</Label>
<AvField
name="username"
value={this.state.username}
type="text"
className="form-control"
id="username"
validate={{ email: true, required: true }}
placeholder="Enter username"
/>
</div>
<div className="auth-form-group-custom mb-4">
<i className="ri-lock-2-line auti-custom-input-icon"></i>
<Label htmlFor="userpassword">Password</Label>
<AvField
name="password"
value={this.state.password}
type="password"
className="form-control"
id="userpassword"
placeholder="Enter password"
/>
</div>
{/* <div className="form-check">
<Input type="checkbox" className="form-check-input" id="customControlInline" />
<Label className="form-check-label" htmlFor="customControlInline">Remember me</Label>
</div> */}
<div className="mt-4 text-center">
<Button
color="primary"
className="w-md waves-effect waves-light"
type="submit"
>
Log In
</Button>
</div>
{/* <div className="mt-4 text-center">
<Link to="/forgot-password" className="text-muted"><i className="mdi mdi-lock me-1"></i> Forgot your password?</Link>
</div> */}
</AvForm>
</div>
<div className="mt-5 text-center">
<p>
Don't have an account ?{" "}
<Link
to="/register"
className="fw-medium text-primary"
>
{" "}
Register{" "}
</Link>{" "}
</p>
{/* <p>© 2021 Nazox. Crafted with <i className="mdi mdi-heart text-danger"></i> by Themesdesign</p> */}
</div>
</div>
</Col>
</Row>
</div>
</div>
</Col>
<Col lg={8}>
<div className="authentication-bg">
<div className="bg-overlay"></div>
</div>
</Col>
</Row>
</Container>
</div>
</React.Fragment>
);
}
}
const mapStatetoProps = (state) => {
const { loginError } = state.Login;
return { loginError };
};
export default withRouter(
connect(mapStatetoProps, { checkLogin, apiError, loginAction })(Login)
);

You should consider to implement some Error Boundaries (if using React 16+);
If errors are not caught by any error boundary, this will result in unmounting of the whole component tree (https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html).
If the unmounting in turn changes something inside the store, this will cause re-rendering again in an infinite loop.
One error could occur (and probably not caught if you don't have Error Boundaries) beacuse you're using JSON.parse(localStorage.getItem("username")) in setState().
If the item inside localStorage is a normal string (as probably is), JSON.parse(<string>) will result in an error.

Related

Formik Error Passing To Submit Not Working?

Hi guys i want to pass 'error' coming from nodejs backend to onsubmit the problem that even if the error passes i still navigate to login page
this is my code :
import "./form_inscription.css";
import { useState } from "react";
import { useFormik } from "formik";
import { validationSchemaBase } from "./formsScema";
//reactstrap componenets
import { FormGroup, Label, Input, Alert } from "reactstrap";
//icons and assets
import ArrowLeft from "../../../../assets/icons/Arrow-Left.png";
import { useDispatch, useSelector } from "react-redux";
// import { registerUser } from "../../../../store/features/authentication/inscription/inscriptionThunk";
import { registerUser } from "../../../../store/features/authentication/authentificationThunk";
import { useNavigate } from "react-router-dom";
import { Eye, EyeOff } from "react-feather";
import { useEffect } from "react";
const FormIscriptionEtape1 = () => {
const [checkboxError, setCheckboxError] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const { error } = useSelector((store) => store.authentification);
const onSubmit = (values) => {
if (values.password === values.passConfirm) {
//checkbox error handling conditions
if (values.cPartner || values.aPartner || values.sPartner) {
setCheckboxError(false);
dispatch(registerUser(values));
if (!error) {
navigate("/login");
}
} else {
setCheckboxError(true);
}
//catch error handling
} else {
console.log("mot de passe non conforme!!");
}
};
const togglePasswordVisibility = () => {
setShowPassword((prevState) => !prevState);
};
const dispatch = useDispatch();
//formik data management
const {
values,
handleChange,
handleBlur,
handleSubmit,
setFieldValue,
errors,
touched,
} = useFormik({
initialValues: {
email: "",
password: "",
passConfirm: "",
cPartner: false,
aPartner: false,
sPartner: false,
},
validationSchema: validationSchemaBase.test(
"one check-box-required",
"Veuillez sélectionner le type de votre organsime",
(values) => values.aPartner || values.sPartner || values.cPartner
),
onSubmit,
});
//handle check boxes
const handleChangeBox = (event) => {
const { name, value, checked } = event.target;
if (name === "cPartner" || name === "aPartner" || name === "sPartner") {
setFieldValue(name, checked);
if (name === "cPartner") {
setFieldValue("aPartner", false);
setFieldValue("sPartner", false);
setCheckboxError(false);
} else if (name === "aPartner") {
setFieldValue("cPartner", false);
setFieldValue("sPartner", false);
setCheckboxError(false);
} else {
setFieldValue("cPartner", false);
setFieldValue("aPartner", false);
setCheckboxError(false);
}
} else {
setFieldValue(name, value);
setCheckboxError(false);
}
};
//navigation to Login screen through the back button temporary will be deleted in the future
const navigate = useNavigate();
const handleNavigateLogin = () => {
navigate("/login");
};
return (
<div>
<div className="w-100 d-flex flex-column justify-content-center align-items-center">
<div className="w-50 mb-1">
<FormGroup className="mt-2">
<Label
className="label_title_inscription text_600_nrm"
for="exampleEmail"
>
Email
</Label>
<Input
className="input_text_off"
type="email"
name="email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
/>
{errors.email && (
<p className="validation_problems">{errors.email}</p>
)}
</FormGroup>
</div>
<div className="w-50 mb-1">
<div className=" justify-content-between">
<FormGroup className="auth-login-form mt-2">
<Label
className="label_title_inscription text_600_nrm"
for="examplePassword"
>
Mot de passe
</Label>
<Input
className="input_text_off"
type={showPassword ? "text" : "password"}
name="password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
/>
{/* <div
className="password-visibility-icon"
onClick={togglePasswordVisibility}
>
{showPassword ? <Eye size={20} /> : <EyeOff size={20} />}
</div> */}
{errors.password && touched.password && (
<p className="validation_problems">{errors.password}</p>
)}
</FormGroup>
</div>
</div>
<div className="w-50 mb-1">
<div className=" justify-content-between">
<FormGroup className="auth-login-form mt-2">
<Label
className="label_title_inscription text_600_nrm"
for="examplePassword"
>
Confirmation mot de passe
</Label>
<Input
className="input_text_off"
type={showPassword ? "text" : "password"}
name="passConfirm"
value={values.passConfirm}
onChange={handleChange}
onBlur={handleBlur}
/>
{/* <div
className="password-visibility-icon"
onClick={togglePasswordVisibility}
>
{showPassword ? <Eye size={20} /> : <EyeOff size={20} />}
</div> */}
{errors.passConfirm && touched.passConfirm && (
<p className="validation_problems">{errors.passConfirm}</p>
)}
</FormGroup>
</div>
</div>
</div>
{/* checkbox section */}
<p className="text-center mt-5 checkbox_text_inscription text_600_nrm">
Vous êtes
</p>
{checkboxError && (
<p className="validation_problems error_validation_check">
Veuillez sélectionner le type de votre organsime
</p>
)}
<div className="d-flex justify-content-center checkbox">
<div className="form-check d-flex checks_gap">
<Input
type="checkbox"
className="form-check"
name="cPartner"
checked={values.cPartner}
onChange={handleChangeBox}
/>
<Label
className="form-check-Label checkbox_text_inscription text_600_nrm"
htmlFor="formrow-customCheck"
>
Commercial
</Label>
</div>
<div className="form-check d-flex checks_gap">
<Input
type="checkbox"
className="form-check"
name="sPartner"
checked={values.sPartner}
onChange={handleChangeBox}
/>
<Label
className="form-check-Label checkbox_text_inscription text_600_nrm"
htmlFor="formrow-customCheck"
>
Educatif
</Label>
</div>
<div className="form-check d-flex checks_gap">
<Input
type="checkbox"
className="form-check"
name="aPartner"
checked={values.aPartner}
onChange={handleChangeBox}
/>
<Label
className="form-check-Label checkbox_text_inscription text_600_nrm"
htmlFor="formrow-customCheck"
>
Associatif
</Label>
</div>
</div>
{error ? <Alert color="danger">{error.message}</Alert> : null}{" "}
<div className="w-100 d-flex justify-content-end mt-5">
{/* <button
className="d-flex align-items-center justify-content-center btn_next_back"
onClick={handleNavigateLogin}
>
<img src={ArrowLeft} alt="" />
</button> */}
<button type="submit" className="btn_next_step" onClick={handleSubmit}>
Suivant
</button>
</div>
</div>
);
};
export default FormIscriptionEtape1;
i tried passing error to onsubmit props but it gives me undefined everytime so the only way that my error passes is the way i am writing the code right now.
Maybe it's because of this typo?
(store) => store.authentification
it should probably be "authentication"
(store) => store.authentication

React - multi step form with checkbox in child step does not set to true

I am creating a multistep form in react. The Parent component has 3 child components which are the steps of the form. In the first step I have 4 text inputs and need a checkbox to allow wpp communication, the problem is that i can't set the state of the checkbox to true when is clicked.
The parent component is something like this:
import React from 'react';
import FormStep0 from './formStepZero';
import FormStep1 from './formStepOne';
class VendeForm extends React.Component {
constructor(props) {
super(props)
this.state = {
currentStep: 0,
nombre: '',
apellido: '',
celular: '',
email: '',
username: '',
password: '',
checkbox: false,
}
}
handleChange = event => {
const {name, value} = event.target
this.setState({
[name]: value
})
}
handleSubmit = event => {
event.preventDefault()
const { email, username, password, nombre, apellido, celular,checkbox } = this.state
alert(`Your registration detail: \n
Email: ${email} \n
Username: ${username} \n
Password: ${password} \n
Nombre: ${nombre} \n
Apellido: ${apellido} \n
Celular: ${celular} \n
Checkbox: ${checkbox} \n`)
}
_next = () => {
let currentStep = this.state.currentStep
currentStep = currentStep >= 2? 3: currentStep + 1
this.setState({
currentStep: currentStep
})
}
_prev = () => {
let currentStep = this.state.currentStep
currentStep = currentStep <= 0? 0: currentStep - 1
this.setState({
currentStep: currentStep
})
}
/*
* the functions for our button
*/
previousButton() {
let currentStep = this.state.currentStep;
if(currentStep > 1){
return (
<div className='vertical-center'>
<button
className="btn btn-secondary float-right mx-2 my-2"
type="button" onClick={this._prev}>
Previous
</button>
</div>
)
}
return null;
}
nextButton(){
let currentStep = this.state.currentStep;
if(currentStep <3 && currentStep >=1){
return (
<div className='vertical-center'>
<button
className="btn primary-bg-style float-left mx-2 my-2"
type="button" onClick={this._next}>
Siguiente
</button>
</div>
)
}
return null;
}
empecemosButton(){
let currentStep = this.state.currentStep;
if(currentStep === 0){
return (
<div className='vertical-center'>
<button
className="btn primary-bg-style"
type="button" onClick={this._next}>
Vamos!
</button>
</div>
)
}
return null;
}
render() {
return (
<React.Fragment>
{/*render the form steps and pass required props in*/}
<Step0
currentStep={this.state.currentStep}
handleChange={this.handleChange}
/>
<div className="container d-flex flex-column py-2">
<form onSubmit={this.handleSubmit}>
<Step1
currentStep={this.state.currentStep}
handleChange={this.handleChange}
nombre={this.state.nombre}
apellido={this.state.apellido}
celular={this.state.celular}
email={this.state.email}
checkbox={this.state.checkbox}
/>
<Step2
currentStep={this.state.currentStep}
handleChange={this.handleChange}
username={this.state.username}
/>
<Step3
currentStep={this.state.currentStep}
handleChange={this.handleChange}
password={this.state.password}
/>
</form>
<div className='prev-next-btn'>
{this.previousButton()}
{this.nextButton()}
</div>
{this.empecemosButton()}
</div>
</React.Fragment>
);
}
}
function Step0(props){
if (props.currentStep !== 0) {
return null
}
return(
<div className="vertical-center"> {/*<!--^--- Added class --> */}
...
</div>
)
}
function Step1(props) {
if (props.currentStep !== 1) {
return null
}
return(
<div className="form-group">
<div className="vertical-center">
<div className="container">
<h1 className='pb-4 px-2'>Datos de Contacto</h1>
<CircleSteps currentStep={props.currentStep} />
<FormStep1 nombre={props.nombre}
apellido={props.apellido}
celular={props.celular}
email={props.email}
checkbox={props.checkbox}
handleChange = {props.handleChange}
/>
</div>
</div>
</div>
);
}
export default VendeForm;
and the child component where is the checkbox is:
import React from 'react';
import {Col, Row,Container} from 'reactstrap'
function FormStep1(props) {
return(
<div>
<Container className="vende-form-container pt-3">
<Row className='align-items-center justify-content-center'>
<Col md={4} sm={12}>
<div className="form-group">
<label htmlFor="nombre">Nombre</label>
<input
className="form-control"
id="nombre"
name="nombre"
type="text"
placeholder="Escribe tu nombre"
value={props.nombre}
onChange={props.handleChange}
/>
</div>
</Col>
<Col md={4} sm={12} >
<div className="form-group">
<label htmlFor="apellido">Apellido</label>
<input
className="form-control"
id="apellido"
name="apellido"
type="text"
placeholder="Escribe tu apellido"
value={props.apellido}
onChange={props.handleChange}
/>
</div>
</Col>
</Row>
<Row className='align-items-center justify-content-center'>
<Col md={4} sm={12}>
<div className="form-group">
<label htmlFor="celular">Celular</label>
<input
className="form-control"
id="celular"
name="celular"
type="text"
placeholder="Escribe tu celular"
value={props.celular}
onChange={props.handleChange}
/>
</div>
</Col>
<Col md={4} sm={12}>
<div className="form-group">
<label htmlFor="email">Email</label>
<input
className="form-control"
id="email"
name="email"
type="text"
placeholder="Escribe tu email"
value={props.email}
onChange={props.handleChange}
/>
</div>
</Col>
</Row>
<Row className='align-items-center justify-content-start'>
{/* checkbox allowing whatsapp communication */}
<Col sm={{size:6, offset:2}} md={{size:3, offset:2}}>
<div className="form-check">
<input
className="form-check-input"
id="wppCheckbox"
name="controlled"
type="checkbox"
checked={props.checkbox}
onChange={props.handleChange}
/>
<label className="form-check-label" htmlFor="wppCheckbox">
Aceptas comunicacion via Whatsapp
</label>
</div>
</Col>
</Row>
</Container>
</div>
);
}
export default FormStep1;
The behavior that currently I have is that i click the checkbox but remains in blank, also the others fields of the form are working well and are passed to state properly
If I understand correctly, your checkbox is handled by generic handleChange() function:
handleChange = event => {
const {name, value} = event.target
this.setState({
[name]: value
})
}
Simplest thing you could try for debugging is just logging what you get in that function when you click the checkbox. Most probably in this case you are always getting the same value ("on") hence nothing changes in the state.
I would suggest either use a dedicated handler, or modify this one to be sth like
handleChange = event => {
const {name, type, value} = event.target
if (type === 'checkbox') {
return this.setState({
[name]: event.target.checked
})
}
this.setState({
[name]: value
})
}

React - Uncaught Error: Element type is invalid

[enter image description here]
Hello, I'm a new developer who has been working as a frontend developer for less than a year.
I'm making a blog project to study react.
However, the following error occurred in the middle.
I've been trying for a long time to figure this out, but I just couldn't find the answer.
There are many other files, but the error file code that I think is most likely is as follows.
I would really appreciate your help.
import React, { useEffect, Fragment } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Helmet } from "react-helmet";
import {
POST_DETAIL_LOADING_REQUEST,
POST_DELETE_REQUEST,
USER_LOADING_REQUEST,
POST_DETAIL_LOADING_SUCCESS,
POST_DETAIL_LOADING_FAILURE,
} from "../../redux/types";
import { Button, Row, Col, Container } from "reactstrap";
import { Link } from "react-router-dom";
import CKEditor from "#ckeditor/ckeditor5-react";
import GrowingSpinner from "../../components/spinner/Spinner";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import {
faPencilAlt,
faCommentDots,
faMouse,
} from "#fortawesome/free-solid-svg-icons";
import BalloonEditor from "#ckeditor/ckeditor5-editor-balloon/src/ballooneditor";
import { editorConfiguration } from "../../components/editor/EditorConfig";
import Comments from "../../components/comments/Comments";
const PostDetail = (req) => {
const dispatch = useDispatch();
const { postDetail, creatorId, title, loading } = useSelector(
(state) => state.post
);
const { userId, userName } = useSelector((state) => state.auth);
const { comments } = useSelector((state) => state.comment);
console.log(req);
useEffect(() => {
dispatch({
type: POST_DETAIL_LOADING_REQUEST,
payload: req.match.params.id,
});
dispatch({
type: USER_LOADING_REQUEST,
payload: localStorage.getItem("token"),
});
}, [dispatch, req.match.params.id]);
const onDeleteClick = () => {
dispatch({
type: POST_DELETE_REQUEST,
payload: {
id: req.match.params.id,
token: localStorage.getItem("token"),
},
});
};
const EditButton = (
<Fragment>
<Row className="d-flex justify-content-center pb-3">
<Col className="col-md-3 mr-md-3">
<Link to="/" className="btn btn-primary btn-block">
Home
</Link>
</Col>
<Col className="col-md-3 mr-md-3">
<Link
to={`/post/${req.match.params.id}/edit`}
className="btn btn-success btn-block"
>
Edit Post
</Link>
</Col>
<Col className="col-md-3">
<Button className="btn-block btn-danger" onClick={onDeleteClick}>
Delete
</Button>
</Col>
</Row>
</Fragment>
);
const HomeButton = (
<Fragment>
<Row className="d-flex justify-content-center pb-3">
<Col className="col-sm-12 com-md-3">
<Link to="/" className="btn btn-primary btn-block">
Home
</Link>
</Col>
</Row>
</Fragment>
);
const Body = (
<>
{userId === creatorId ? EditButton : HomeButton}
<Row className="border-bottom border-top border-primary p-3 mb-3 d-flex justify-content-between">
{(() => {
if (postDetail && postDetail.creator) {
return (
<Fragment>
<div className="font-weight-bold text-big">
<span className="mr-3">
<Button color="info">
{postDetail.category.categoryName}
</Button>
</span>
{postDetail.title}
</div>
<div className="align-self-end">{postDetail.creator.name}</div>
</Fragment>
);
}
})()}
</Row>
{postDetail && postDetail.comments ? (
<Fragment>
<div className="d-flex justify-content-end align-items-baseline small">
<FontAwesomeIcon icon={faPencilAlt} />
<span> {postDetail.date}</span>
<FontAwesomeIcon icon={faCommentDots} />
<span>{postDetail.comments.length}</span>
<FontAwesomeIcon icon={faMouse} />
<span>{postDetail.views}</span>
</div>
<Row className="mb-3">
<CKEditor
editor={BalloonEditor}
data={postDetail.contents}
config={editorConfiguration}
disabled="true"
/>
</Row>
<Row>
<Container className="mb-3 border border-blue rounded">
{Array.isArray(comments)
? comments.map(
({ contents, creator, date, _id, creatorName }) => (
<div key={_id}>
<Row className="justify-content-between p-2">
<div className="font-weight-bold">
{creatorName ? creatorName : creator}
</div>
<div className="text-small">
<span className="font-weight-bold">
{date.split[0]}
</span>
<span className="font-weight-light">
{date.split[1]}
</span>
</div>
</Row>
<Row className="p-2">
<div>{contents}</div>
</Row>
<hr />
</div>
)
)
: "Creator"}
<Comments
id={req.match.params.id}
userId={userId}
userName={userName}
/>
</Container>
</Row>
</Fragment>
) : (
<h1>hi</h1>
)}
</>
);
console.log(comments, "Comments");
return (
<div>
<Helmet title={`Post | ${title}`} />
{loading === true ? GrowingSpinner : Body}
</div>
);
};
export default PostDetail;
<Helmet title={Post | ${title}} />
Even though you wrote the syntax above, the title value is not output.
enter image description here
The structure is as follows:
(postWrite) -> write post + click button -> save post + move postDetail page (error)
+) The code is quite long, but I'm sorry I couldn't highlight it. As for me, I have no idea which part of this file is the problem....
Just looking through the code and the error message you're seeing, there doesn't appear to be anything wrong with the exported component. Rather, it seems that the way you're importing the component might be wrong.
export default PostDetail
This means that you'll need to import the component using this syntax:
import PostDetail from './path-to-component'
I too had the same problem, mine was fixed when I used
import { CKEditor } from "#ckeditor/ckeditor5-react";
in place of
import CKEditor from "#ckeditor/ckeditor5-react";

React error : Invalid prop `class` supplied to React.Fragment

enter image description here
Hello, we are currently experiencing the following errors in React. I'm not sure what's wrong with this error and it's being sent out. I tried to cover it with a tag instead of a <React.Fragment>, but the error above keeps appearing on the screen.
I think you're saying the wrong value is in the wrong tag. but I think, not found a problem with my code.
What could be wrong? I ask for your help me.
I attach my code.
import React, { useEffect, Fragment } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Helmet } from "react-helmet";
import {
POST_DETAIL_LOADING_REQUEST,
POST_DELETE_REQUEST,
USER_LOADING_REQUEST,
} from "../../redux/types";
import { Button, Row, Col } from "reactstrap";
import { Link } from "react-router-dom";
import CKEditor from "#ckeditor/ckeditor5-react";
import GrowingSpinner from "../../components/spinner/Spinner";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import {
faPencilAlt,
faCommentDots,
faMouse,
} from "#fortawesome/free-solid-svg-icons";
import BallonEditor from "#ckeditor/ckeditor5-editor-balloon/src/ballooneditor";
import BalloonEditor from "#ckeditor/ckeditor5-editor-balloon/src/ballooneditor";
import { editorConfiguration } from "../../components/editor/EditorConfig";
const PostDetail = (req) => {
const dispatch = useDispatch();
const { postDetail, creatorId, title, loading } = useSelector(
(state) => state.post
);
const { userId, userName } = useSelector((state) => state.auth);
console.log(req);
useEffect(() => {
dispatch({
type: POST_DETAIL_LOADING_REQUEST,
payload: req.match.params.id,
});
dispatch({
type: USER_LOADING_REQUEST,
payload: localStorage.getItem("token"),
});
});
const onDeleteClick = () => {
dispatch({
type: POST_DELETE_REQUEST,
payload: {
id: req.match.params.id,
token: localStorage.getItem("token"),
},
});
};
const EditButton = (
<div>
<Row className="d-flex justify-content-center pb-3">
<Col className="col-md-3 mr-md-3">
<Link to="/" className="btn btn-primary btn-block">
Home
</Link>
</Col>
<Col className="col-md-3 mr-md-3">
<Link
to={`/post/${req.match.params.id}/edit`}
className="btn btn-success btn-block"
>
Edit Post
</Link>
</Col>
<Col className="col-md-3">
<Button className="btn-block btn-danger" onClick={onDeleteClick}>
Delete
</Button>
</Col>
</Row>
</div>
);
const HomeButton = (
<div>
<Row className="d-flex justify-content-center pb-3">
<Col className="col-sm-12 com-md-3">
<Link to="/" className="btn btn-primary btn-block">
Home
</Link>
</Col>
</Row>
</div>
);
const Body = (
<div>
{userId === creatorId ? EditButton : HomeButton}
<Row className="border-bottom border-top border-primary p-3 mb-3 d-flex justify-content-between">
{(() => {
if (postDetail && postDetail.creator) {
return (
<div>
<div className="font-weight-bold text-big">
<span className="mr-3">
<Button color="info">
{postDetail.category.categoryName}
</Button>
</span>
{postDetail.title}
</div>
<div className="align-self-end">{postDetail.creator.name}</div>
</div>
);
}
})()}
</Row>
{postDetail && postDetail.comments ? (
<div>
<div className="d-flex justify-content-end align-items-baseline small">
<FontAwesomeIcon icon={faPencilAlt} />
<span> {postDetail.date}</span>
<FontAwesomeIcon icon={faCommentDots} />
<span>{postDetail.comments.length}</span>
<FontAwesomeIcon icon={faMouse} />
<span>{postDetail.views}</span>
</div>
<Row className="mb-3">
<CKEditor
editor={BalloonEditor}
data={postDetail.contents}
config={editorConfiguration}
disabled="true"
/>
</Row>
</div>
) : (
<h1>hi</h1>
)}
</div>
);
return (
<div>
<Helmet title={`Post | ${title}`} />
{loading === true ? GrowingSpinner : Body}
</div>
);
};
export default PostDetail;
It seems to be a small syntax error, your final return statement should be :
return (
<div>
<Helmet title={`Post | ${title}`} />
{loading === true ? <GrowingSpinner /> : <Body />}
</div>
);

Why I cannot type continuously in react Input field when passing values to another component using props

I am trying to pass values through props from one component to another.
Parent component is InstructorLoginForm and child component is InstructorLoginFormComponent
Everything works fine but the problem is I cannot type in input text field continuously
I try to type username, it types one letter and then it kind loses the focus into the input field, so I have to again click on the input field and type another(single) letter and again focus loses
This is same for the password field too.
Hers is my parent component InstructorLoginForm.jsx
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import InstructorProfile from "./instructor-profile";
import InstructorLoginFormComponent from "./instructor-login-form-component";
export default class InstructorLoginForm extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: ""
};
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangePassword = this.onChangePassword.bind(this);
this.handleOnClick = this.handleOnClick.bind(this);
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onChangePassword(e) {
this.setState({
password: e.target.value
});
}
handleOnClick (){
e.preventDefault();
this.props.history.push(`/instructor/${this.state.username}`);
}
render() {
return (
<Router>
<Switch>
<Route
exact
path="/login"
component={props => (
<InstructorLoginFormComponent
{...props}
username = {this.state.username}
password = {this.state.password}
handleOnClick = {this.handleOnClick}
onChangeUsername = {this.onChangeUsername}
onChangePassword = {this.onChangePassword}
/>
)}
/>
<Route
path={"/instructor/:instructorId"}
component={InstructorProfile}
/>
</Switch>
</Router>
);
}
}
And here is my child component InstructorLoginFormComponent.jsx
import React, { Component } from "react";
import { Link } from "react-router-dom";
export default class InstructorLoginFormComponent extends Component {
constructor(props) {
super(props);
}
componentDidMount(){
console.log(this.props);
}
render() {
return (
<div className="container h-100" style={{ marginTop: 100 }}>
<div className="d-flex justify-content-center h-100">
<div className="user_card bg-dark">
<div className="d-flex justify-content-center">
</div>
<div
className="d-flex justify-content-center form_container"
style={{ marginTop: 0 }}
>
<form>
<div className="input-group mb-3">
<div className="input-group-append">
<span className="input-group-text bg-info">
<i className="fa fa-user" />
</span>
</div>
<input
value={this.props.username}
onChange={this.props.onChangeUsername}
type="text"
name="username"
className="form-control input_user"
placeholder="username"
/>
</div>
<div className="input-group mb-2">
<div className="input-group-append">
<span className="input-group-text bg-info">
<i className="fa fa-lock" />
</span>
</div>
<input
value={this.props.password}
onChange={this.props.onChangePassword}
type="password"
name="passwordbutton"
className="form-control input_user"
placeholder="password"
/>
</div>
<div className="form-group">
<div className="custom-control custom-checkbox">
<input
type="checkbox"
className="custom-control-input"
id="customControlInline"
/>
<label
className="custom-control-label"
htmlFor="customControlInline"
style={{ color: "#ffffff" }}
>
Remember me
</label>
</div>
</div>
</form>
</div>
<div className="d-flex justify-content-center mt-3 login_container">
<button
// to={`/instructor/${this.props.username}`}
onClick={this.props.handleOnClick}
type="button"
className="btn login_btn bg-info"
>
Login
</button>
</div>
</div>
</div>
</div>
);
}
}
Can someone help me why this happens and how to resolve it?
When you type text, the state of the parent component updates and render function calls again. You used
<Route component={...} />
it calls React.createElement at every render, so old child component unmounts and router creates new instance, focus loses.
To fix this issue use
<Route render={<InstructorLoginFormComponent ... />} />
it also provides {match, location, history} props to child, but does not unmount it when parent state changed.
Sorry to put it this way, but this is poor architecture along with a few mistakes in syntax.
You should have all routes in your App.js file and everything else in your Component file (should actually be a Container.js file and a Component.js file, but for another time).
You only need one onChange event (note change to the function structure).
The below behaves as it should.
Please note the handleOnClick should have (e), that should be throwing an error.
Please note password name in the input has been corrected to password, from password button
App.js;
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import InstructorProfile from "./instructor-profile";
import InstructorLoginFormComponent from "./instructor-login-form-component";
export default class App extends Component {
render() {
return (
<Router>
<Switch>
<Route
exact
path="/login"
component={InstructorLoginFormComponent }
/>
<Route
path={"/instructor/:instructorId"}
component={InstructorProfile}
/>
</Switch>
</Router>
);
}
}
and InstructorLoginFormComponent;
import React, { Component } from "react";
import { Link } from "react-router-dom";
export default class InstructorLoginFormComponent extends Component {
constructor(props) {
super(props)
this.state = {
username: "",
password: ""
}
this.onChange = this.onChange.bind(this)
this.handleOnClick = this.handleOnClick.bind(this)
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value
})
}
handleOnClick (e) {
e.preventDefault()
this.props.history.push(`/instructor/${this.state.username}`)
}

render() {
const { username, password } = this.state
return (
<div className="container h-100" style={{ marginTop: 100 }}>
<div className="d-flex justify-content-center h-100">
<div className="user_card bg-dark">
<div className="d-flex justify-content-center">
</div>
<div
className="d-flex justify-content-center form_container"
style={{ marginTop: 0 }}
>
<form>
<div className="input-group mb-3">
<div className="input-group-append">
<span className="input-group-text bg-info">
<i className="fa fa-user" />
</span>
</div>
<input
value={username}
onChange={this.onChange}
type="text"
name="username"
className="form-control input_user"
placeholder="username"
/>
</div>
<div className="input-group mb-2">
<div className="input-group-append">
<span className="input-group-text bg-info">
<i className="fa fa-lock" />
</span>
</div>
<input
value={password}
onChange={this.onChange}
type="password"
name="password"
className="form-control input_user"
placeholder="password"
/>
</div>
<div className="form-group">
<div className="custom-control custom-checkbox">
<input
type="checkbox"
className="custom-control-input"
id="customControlInline"
/>
<label
className="custom-control-label"
htmlFor="customControlInline"
style={{ color: "#ffffff" }}
>
Remember me
</label>
</div>
</div>
</form>
</div>
<div className="d-flex justify-content-center mt-3 login_container">
<button
// to={`/instructor/${this.props.username}`}
onClick={this.props.handleOnClick}
type="button"
className="btn login_btn bg-info"
>
Login
</button>
</div>
</div>
</div>
</div>
);
}
}

Categories

Resources