React useState not updating the states on submit form - reactjs

const [user, setuser] = useState({
fName: '', lName: '', password: '', email: '', username: ''
})
const [fNameError, setfNameError] = useState('');
const [lNameError, setlNameError] = useState('');
const [emailError, setemailError] = useState('');
const [passwordError, setpasswordError] = useState('');
const [usernameError, setusernameError] = useState('');
const changeHandler = (e) => {
setuser({
...user, [e.currentTarget.name]: e.currentTarget.value
})
}
const inputChecker = () => {
user.fName === '' || user.fName.length < 3 ? setfNameError('invalid') : setfNameError('valid');
user.lName === '' || user.lName.length < 3 ? setlNameError('invalid') : setlNameError('valid');
user.username === '' || user.username.length < 5 ? setusernameError('invalid') : setusernameError('valid');
user.password === '' || user.password.length < 6 ? setpasswordError('invalid') : setpasswordError('valid');
validateEmail(user.email) ? setemailError('valid') : setemailError('invalid');
if (fNameError == 'valid' && lNameError == 'valid' && emailError == 'valid' && passwordError == 'valid' && usernameError == 'valid') {
if (fNameError == 'valid') {
return true
}
return false
}
const submitHandler = (e) => {
e.preventDefault();
//
On submitting the form and calling the submitHandler if all errors
in the inputChecker function are valid I need inputChecker to return
true but it returns false on first click even when all are valid but
when i click it for the second time it return true and below check works
// Can someone tell me what I am doing wrong
if (inputChecker()) {
console.log(user);
}
}

Set state is async operation. You are setting the state and then checking its value which will always return you the old one. Thats the reason it returns true in the second time.
Refactor your code as below, and check again.
const inputChecker = () => {
let isFNameValid = true;
let isLNameValid = true;
let isUsernameValid = true;
let isPasswordValid = true;
let isEmailValid = true;
if(user.fName === '' || user.fName.length < 3) {
setfNameError('invalid');
isFNameValid = false;
}
else {
setfNameError('valid');
isFNameValid = true;
}
if(user.lName === '' || user.lName.length < 3) {
setlNameError('invalid');
isLNameValid = false;
}
else {
setlNameError('valid');
isLNameValid = true;
}
if(user.username === '' || user.username.length < 5) {
setusernameError('invalid');
isUsernameValid = false;
}
else {
setusernameError('valid');
isUsernameValid = true;
}
if(user.password === '' || user.password.length < 6) {
setpasswordError('invalid');
isPasswordValid = false;
}
else {
setpasswordError('valid');
isPasswordValid = true;
}
if(validateEmail(user.email)) {
setemailError('valid');
isEmailValid = true;
}
else {
setemailError('invalid');
isEmailValid = false;
}
if (isFNameValid && isLNameValid && isUsernameValid && isPasswordValid && isEmailValid) {
return true;
} else
return false;
}

Related

How do I fix this bug with how my data is being rendered in React Native?

I am trying to push data into state, but it's not pushing the way I want it to. Whenever it pushes the data, when the data gets rendered, it shows the same distance multiple times rather than one time. I am not sure what I'm doing wrong. I attached my code at the bottom.
const d = new Date();
const shopArray = [];
const [number, setNumber] = useState(null);
const [data, setData] = useState(false);
const weekday = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
const currentDay = weekday[new Date().getDay()];
var distanceArray = [];
const rawTime = d.toString().slice(16, 21);
useEffect(() => {
const unsubscribe = () => {
var i = 0;
const shopOpening = [];
const shopClosing = [];
db.collection("shops")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// Get Shop Availability
const hourObj = doc.data().hoursOfOps;
const timings = hourObj[currentDay];
shopOpening.push(timings[0]);
shopClosing.push(timings[1]);
let [hours, minutes] = rawTime.split(":");
const [opening, openingModifier] = timings[0].split(" ");
let [openingHours, openingMinutes] = opening.split(":");
if (openingHours === "12" && modifier == "AM") {
openingHours = "00";
}
if (openingModifier === "PM" && openingHours !== 12) {
openingHours = parseInt(openingHours, 10) + 12;
}
// Closing Time in Military Time
const [closing, closingModifier] = timings[1].split(" ");
let [closingHours, closingMinutes] = closing.split(":");
if (closingHours === "12") {
closingHours = "00";
}
if (closingModifier === "PM") {
closingHours = parseInt(closingHours, 10) + 12;
}
const userHour = parseInt(hours);
const openingHour = parseInt(openingHours);
const closingHour = parseInt(closingHours);
const shopAvailability = [];
if (userHour >= openingHour && userHour <= closingHour) {
if (
userHour === closingHour &&
closingMinutes !== "0" &&
minutes < closingMinutes
) {
shopAvailability.push("Open");
} else if (
userHour === closingHour &&
closingMinutes !== "0" &&
minutes > closingMinutes
) {
shopAvailability.push("Closed");
} else if (userHour === closingHour && closingMinutes == 0) {
shopAvailability.push("Closed");
} else if (
userHour === openingHour &&
userMinutes >= openingMinutes
) {
shopAvailability.push("Open");
} else if (
userHour === openingHour &&
userMinutes < openingMinutes
) {
shopAvailability.push("Closed");
} else {
shopAvailability.push("Open");
}
} else if (userHour <= openingHour || userHour >= closingHour) {
shopAvailability.push("Closed");
} else {
shopAvailability.push("Closed");
}
// Get Distance from User
fetch(
`https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=${userLocation}&destinations=${
doc.data().address
}&key=${GOOGLE_MAPS_APIKEY}`
)
.then((res) => res.json())
.then((data) => {
var number = data.rows[0].elements[0].distance.text.split(" ");
setNumber(number[0]);
});
// Push data into an array for iterative rendering
if (number == null || number !== undefined) {
shopArray.push({
name: doc.data().name,
id: doc.id,
hoursOfOps: doc.data().hoursOfOps,
image: doc.data().shop_image,
menu: doc.data().menu,
location: doc.data().address,
distanceK: number + " km",
availability: shopAvailability,
opening: shopOpening[i],
closing: shopClosing[i],
});
}
i = i + 1;
});
setData(shopArray.sort((a, b) => (a.distance < b.distance ? 1 : -1)));
});
};
return unsubscribe;
}, [userLocation, GOOGLE_MAPS_APIKEY]);
Also, when I log num[0], a different number comes up for each instance, but when I render it on the screen, the same number comes up multiple times. I think the issue lies in how I'm setting the data in the state. How do I fix this? Feel free to comment on the post to ask for further clarification.

How to convert a componentDidUpdate to useEffect when prevProps are used in a nested if/else statement?

I'm not sure how to convert this section to fit into a useEffect. I can't pull the prevProps conditional out since it should only run within the loop. I dont think I can just add the props to dependency array either, as I need to do something else whenever selectedCurrency does not change.
public componentDidUpdate(prevProps: Readonly<Props>): void {
if (api != null) {
const MyData: {}[] = [];
api.forEach(el=> {
if (!el.data) {
return;
}
if (selectedCurrency === "") {
el.setDataValue("val1", "-");
el.setDataValue("val2", "-");
el.setDataValue("val3", "-");
el.setDataValue("val4", "-");
} else {
const originalCcy = el.data.Currency;
const exchangeRate = referenceCurrencies
.filter(x => x.originalCurrency === originalCcy)
.flatMap(value => value.conversionCurrencies)
.find(value => value.currency === selectedCurrency);
const middleMarketRate = exchangeRate ? exchangeRate.middleMarketRate : 1;
el.setDataValue("val2", el.data.val2 * middleMarketRate);
el.setDataValue(
"val3",
el.data.val3 * middleMarketRate
);
el.setDataValue("val1", middleMarketRate);
if (
prevProps.dateFrom === dateFrom &&
prevProps.dateTo === dateTo &&
prevProps.selectedCurrency !== selectedCurrency
) {
const dateToMoment = moment(dateTo);
const dateFromMoment = moment(dateFrom);
const totalValBalCols = dateToMoment.diff(dateFromMoment, "days");
for (let i = 0; i <= totalValBalCols; i += 1) {
const dayDiff = i;
const currentDate = moment(dateFrom)
.add(dayDiff, "days")
.format("DD-MMM-YYYY");
el.setDataValue(
"refCol",
el.data[currentDate]
);
}
} else {
MyData.push(el.data);
}
}
});
}
}
You can use useRef() to hold the previous props, with a 2nd useEffect() to update preProps.current after you check if anything changed.
Example (not tested):
const prevProps = useRef();
useEffect(() => {
// skip the effect since this is the initial render
if(!prevProps.current) return;
api?.forEach(el => {
if (!el.data) return;
if (selectedCurrency === "") {
// Do something
return;
}
if (
prevProps.current.dateFrom === dateFrom &&
prevProps.current.dateTo === dateTo &&
prevProps.current.selectedCurrency !== selectedCurrency
) {
//Do something
return;
}
//Do something else
});
}, [api, dateFrom, dateTo, selectedCurrency]);
useEffect(() => { prevProps.current = props; })

How to adjust valid input check method for SpinButton?

I'm using Office UI Fabric and have a SpinButton implemented. There is some kind of automatic validation that prevents me from using anything apart from numbers as an input. The problem is, I cannot even use the subtract sign.
How can I change that?
I tried implementing my own onValidate() method, to cancel out the default one, and even though it's called, it doesn't stop the SpinButton input from being deleted when different from numbers
onValidate={() => console.log('Validate meeee')}
The whole SpinButton looks like this (it's mixed with JS):
static getNumericBox(formField: EntityFormField, onChange: EntityFormControlOnChangeType): JSX.Element {
let rangeFrom: number = -999999;
let rangeTo: number = 999999;
const controlParams = EntityFormHelpers.getNumericControlParams(formField.controlType);
if (controlParams) {
rangeFrom = controlParams.rangeFrom;
rangeTo = controlParams.rangeTo;
}
return (
<React.Fragment key={formField.fieldName}>
<SpinButton
key={formField.fieldName}
className={'NumericBox ' + this.getValidationClassName(formField)}
label={formField.displayName}
labelPosition={Position.top}
componentRef={(component: any) => {
if (component) {
const inputElement = component._input.current;
const labelElement = inputElement.parentElement.previousSibling.firstChild;
if (formField.validation.isRequired && !formField.displayOnly) {
labelElement.setAttribute('required', '');
}
inputElement.value = formField.value;
inputElement.onkeydown = (event: any) => {
if (event.target.value.toString().length > rangeTo.toString().length + 1 && event.target.value.toString().length > rangeFrom.toString().length + 1) {
event.preventDefault();
event.stopPropagation();
}
};
inputElement.onkeyup = (event: any) => {
let numberValue = Number(event.target.value);
if (!numberValue) {
numberValue = formField.validation.isRequired ? Number(0) : null;
}
onChange(formField.fieldName, numberValue);
};
}
}}
onValidate={() => console.log('Validate meeee')}
onIncrement={(value: string) => {
if (Number(value) + 1 > rangeTo) {
formField.value = value;
} else {
value = String(+value + 1);
onChange(formField.fieldName, value);
formField.value = value;
}
}}
onDecrement={(value: string) => {
if (Number(value) - 1 < rangeFrom) {
formField.value = value;
} else {
value = String(+value - 1);
onChange(formField.fieldName, value);
formField.value = value;
}
}}
value={formField.value}
min={rangeFrom}
max={rangeTo}
step={1}
onBlur={(event: any) => {
const numberValue = Number(event.target.value);
if (numberValue) {
if (numberValue < rangeFrom) {
onChange(formField.fieldName, rangeFrom);
}
else if (numberValue > rangeTo) {
onChange(formField.fieldName, rangeTo);
}
}
}}
disabled={formField.displayOnly}
/>
{this.getDescriptionControl(formField)}
</React.Fragment>);
}
Problem is in the onkeyup methods. Everything kept overwriting as soon as a single key was pressed. A bit of fiddling around fixed the whole thing.
In case anyone is interested, here's the final and working state:
static getNumericBox(formField: EntityFormField, onChange: EntityFormControlOnChangeType): JSX.Element {
let rangeFrom: number = -999999;
let rangeTo: number = 999999;
const controlParams = EntityFormHelpers.getNumericControlParams(formField.controlType);
if (controlParams) {
rangeFrom = controlParams.rangeFrom;
rangeTo = controlParams.rangeTo;
}
return (
<React.Fragment key={formField.fieldName}>
<SpinButton
key={formField.fieldName}
className={'NumericBox ' + this.getValidationClassName(formField)}
label={formField.displayName}
labelPosition={Position.top}
componentRef={(component: any) => {
if (component) {
const inputElement = component._input.current;
const labelElement = inputElement.parentElement.previousSibling.firstChild;
if (formField.validation.isRequired && !formField.displayOnly) {
labelElement.setAttribute('required', '');
}
inputElement.value = formField.value;
inputElement.onkeydown = (event: any) => {
if (event.target.value.toString().length > rangeTo.toString().length + 1 && event.target.value.toString().length > rangeFrom.toString().length + 1) {
event.preventDefault();
event.stopPropagation();
}
};
inputElement.onkeyup = (event: any) => {
const isValidKeyCode =
event.which === KeyCodes.up ||
event.which === KeyCodes.down ||
event.which === KeyCodes.left ||
event.which === KeyCodes.right ||
event.which === KeyCodes.backspace ||
event.which === KeyCodes.del ||
event.which === KeyCodes.a && event.ctrlKey ||
event.which === KeyCodes.x && event.ctrlKey ||
event.which === KeyCodes.c && event.ctrlKey ||
event.which === KeyCodes.v && event.ctrlKey ||
event.which === KeyCodes.subtract ||
event.which === KeyCodes.dash;
const isValidNumberKeyCode = (
(event.which >= KeyCodes.zero && event.which <= KeyCodes.nine) ||
(event.which >= KeyCodes.zero_numpad && event.which <= KeyCodes.nine_numpad)
);
if (!isValidKeyCode && !isValidNumberKeyCode) {
onChange(formField.fieldName, null);
} else if (event.target.value === "-") {
return;
} else {
let numberValue = parseInt(event.target.value);
if (!numberValue && numberValue !== 0) {
numberValue = formField.validation.isRequired ? +"0" : null;
}
onChange(formField.fieldName, numberValue);
}
};
}
}}
onIncrement={(value: string) => {
if (Number(value) + 1 > rangeTo) {
formField.value = value;
} else {
value = String(+value + 1);
onChange(formField.fieldName, value);
formField.value = value;
}
}}
onDecrement={(value: string) => {
if (Number(value) - 1 < rangeFrom) {
formField.value = value;
} else {
value = String(+value - 1);
onChange(formField.fieldName, value);
formField.value = value;
}
}}
value={formField.value}
min={rangeFrom}
max={rangeTo}
step={1}
onBlur={(event: any) => {
const numberValue = Number(event.target.value);
if (numberValue) {
if (numberValue < rangeFrom) {
onChange(formField.fieldName, rangeFrom);
}
else if (numberValue > rangeTo) {
onChange(formField.fieldName, rangeTo);
}
}
}}
disabled={formField.displayOnly}
/>
{this.getDescriptionControl(formField)}
</React.Fragment>);
}

React update state object using hooks (useState) works, but no rerender

I have a weird problem with React hooks (useState).
I have a page which checks my bills and my bank account and checks wether salary is in, and then moves my money to different jars. The page has 2 buttons: check preconditions (salary enough, etc), and run script.
The first one (preconditions) works as expected, also the output (in below code the var currentstate), when I update the state (with setPreconditions) nothing happens.
So, my thought was that state isnt updated, until I found out that when I changed some other field with state (for example salary) the page rerenders and the correct data for currentstate (state preconditions) is displayed.
Why is this happening?
const Bunq = ({auth}) => {
const [accounts, setAccounts] = useState([]);
const [preconditions, setPreconditions] = useState({run: false, succeeded: false, accountsExist: [], balanceSufficient: true, incomeSufficient: true, sparen: null, maandtotaal: 0, balance: null});
const [rekeningen, setRekeningen] = useState([]);
const [salaris, setSalaris] = useState(getLocalStorage('bunq_salaris') || '');
const [eigen_geld, setEigenGeld] = useState(getLocalStorage('bunq_eigen_geld') || '');
const [sparen, setSparen] = useState(0);
const [page_loaded, setPageLoaded] = useState(false);
const [script_running, setScriptRunning] = useState(false);
useEffect(() => {
setLocalStorage('bunq_salaris', salaris);
}, [salaris]);
useEffect(() => {
setLocalStorage('bunq_eigen_geld', eigen_geld);
}, [eigen_geld]);
.......................
const checkPreconditions = () => {
//check
//setScriptRunning(true);
const algemeen_account = getAccountByName("Algemeen");
let maandnummer = (new Date()).getMonth()+1;
let currentstate = preconditions;
currentstate.succeeded = true;
currentstate.maandtotaal = 0;
currentstate.incomeSufficient = true;
currentstate.balanceSufficient = true;
currentstate.balance = algemeen_account.balance.value;
rekeningen.map(rekening => {
currentstate.maandtotaal += rekening["totaal_" + maandnummer];
let foundaccount = getAccountByName(rekening.rekening);
if(foundaccount == null && rekening["totaal_" + maandnummer] > 0){
currentstate.succeeded = false;
currentstate.accountsExist.push(rekening.rekening)
console.log("Rekening bestaat niet: " + rekening.rekening);
}
});
if((parseFloat(algemeen_account.balance.value)) < salaris){
currentstate.balanceSufficient = false;
currentstate.succeeded = false;
}
if((currentstate.maandtotaal + eigen_geld) > salaris){
currentstate.incomeSufficient = false;
currentstate.sparen = 0;
currentstate.succeeded = false;
}else{
currentstate.sparen = (salaris - currentstate.maandtotaal - eigen_geld);
if(currentstate.balanceSufficient){
currentstate.sparen = (currentstate.sparen + (Math.round(algemeen_account.balance.value) - salaris));
}
//console.log(currentstate);
if(currentstate.sparen < 0){
currentstate.sparen = 0;
currentstate.incomeSufficient = false;
currentstate.succeeded = false;
}else{
currentstate.incomeSufficient = true;
}
}
setPreconditions(currentstate);
//setPreconditions('test');
console.log(currentstate, preconditions);
//setScriptRunning(false);
//this.setState({preconditions: currentstate});
}
.........................
return (<div><h1>Bunq</h1>
<DefaultTable data={rekeningen} columns={rekeningColumns} loading={rekeningen.length === 0} pageSize={15}/>
<Form>
<Row>
......................
<Button variant="primary" onClick={() => {checkPreconditions();console.log(preconditions);}} disabled={!page_loaded || script_running}>Controleer</Button>
</Row>
</Form>
<ListGroup>
{JSON.stringify(preconditions)}
{preconditions.balance !== null ?<ListGroup.Item variant="success">Huidig saldo Algemene rekening: {preconditions.balance}</ListGroup.Item> : ""}
{preconditions.accountsExist.map((rek, i) => {return <ListGroup.Item key={i} variant="danger">Rekening {rek} bestaat niet</ListGroup.Item>})}
{preconditions.balanceSufficient === false ? <ListGroup.Item variant="danger">Niet voldoende saldo. Salaris nog niet binnen?</ListGroup.Item> : ""}
{preconditions.incomeSufficient === false ? <ListGroup.Item variant="danger">Niet voldoende inkomen om alle rekeningen te betalen</ListGroup.Item> : ""}
{preconditions.sparen !== null ? <ListGroup.Item variant="success">Er wordt {preconditions.sparen} gespaard</ListGroup.Item> : ""}
</ListGroup>
</div>
);
}
You are mutating your state, so when you call setPreconditions(currentstate) you are updating the state with the exact same object reference, which React will treat as no state being updated.
You can create a copy of the preconditions object instead.
const checkPreconditions = () => {
const algemeen_account = getAccountByName("Algemeen");
let maandnummer = new Date().getMonth() + 1;
let currentstate = { ...preconditions };
// ...
}

How to redirect from react page to express page

Hey I'm looking for redirect a React page to Express page. The purpose is to send a mail if the user forgot his password. I tried to use Router but that send me on 'localhost:3000/forgot_password' and not 'localhost:3001/forgot_password'.
However that works with my submit form in my signup part. Why ?
My code is a bit messy so I'll comment the important part.
Here is the express part :
const bodyParser = require('body-parser')
const express = require('express')
const mysql = require('mysql')
const randomString = require('randomstring')
const bcrypt = require('bcrypt')
const app = express()
const router = express.Router()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
app.use((req, res, next) => {
req.db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '00000000',
database: 'Matcha'
});
next();
});
router.get('/users', (req, res) => {
req.db.query("SELECT * FROM Users;", (err, rows, fields) => {
if(err)
return(res.send(err) && console.log(err));
res.json(rows);
});
});
router.post('/check_signUp', (req, res) => {
console.log(req.body);
const saltRounds = 10;
const password = req.body.password;
bcrypt.hash(password, saltRounds, function(err, hashPassword) {
const randomKey = randomString.generate(15)
console.log(req.body.username, password, req.body.mail, randomKey)
req.db.query(`INSERT INTO Users (username, password, mail, randomKey) VALUES ('${req.body.username}', '${hashPassword}', '${req.body.mail}', '${randomKey}');`, (err, rows, fields) => {
if(err)
return(res.send(err) && console.log(err));
bcrypt.compare('ffffff', '$2b$10$6707gWLRGjqGwKJzXx6Dt.CH00c0rRlioy8KdcWc4ze18LoL2YHeC', function(err, res) {
console.log(res)
});
res.redirect('/');
})
})
})
// HERE IS THE IMPORTANT PART. I need to go in this router.get
router.get('/change_password', (req, res) => {
res.send('OK');
});
// END OF THE IMPORTANT PART
app.use(router)
app.set('port', (process.env.PORT || 3001))
app.listen(app.get('port'), () => {
console.log(`Listening on ${app.get('port')}`)
})
And here the react part :
import React, { Component } from 'react';
import './SignIn.css';
import { BrowserRouter as Router, Link } from 'react-router-dom';
class SignIn extends React.Component {
constructor(props) {
super(props);
this.state = {
valueUsername: '',
valuePassword: '',
users: [],
validLog: '_',
validMessage: '_'
};
this.changeUsername = this.changeUsername.bind(this);
this.changePassword = this.changePassword.bind(this);
this.submitForm = this.submitForm.bind(this);
this.checkMatch = this.checkMatch.bind(this);
}
async componentDidMount() {
const response = await fetch('/users')
const users = await response.json()
this.setState({users: users})
}
changeUsername(event) {
this.setState({valueUsername: event.target.value});
}
changePassword(event) {
this.setState({valuePassword: event.target.value});
}
checkMatch(valueUsername, valuePassword) {
let users = this.state.users;
let valueMatch = 0;
users.forEach((user) => {
console.log(user['username']);
if (user['username'].toUpperCase() === valueUsername.toUpperCase()) {
valueMatch = 1;
console.log(user.password);
if (user.password === valuePassword)
valueMatch = 2;
return;
}
});
return valueMatch;
}
submitForm(event) {
let match = this.checkMatch(this.state.valueUsername, this.state.valuePassword);
console.log(match);
if (match != 2) {
event.preventDefault();
this.setState({valuePassword: ''});
if (match == 1) {
this.setState({validLog: 'Wrong password'});
this.setState({validMessage: 'Forgot it ? Click here'})
}
else
this.setState({validLog: 'Username doesn\'t exist'});
}
}
render() {
let validLogColor;
let validMessageColor;
let validMessage = this.state.validMessage;
if (this.state.validLog === '_')
validLogColor = 'SignIn_validNone';
else
validLogColor = 'SignIn_validRed';
if (this.state.validMessage === '_')
validMessageColor = 'SignIn_validNone'
else if (this.state.validMessage === 'Forgot it ? Click here') {
validMessageColor = 'SignIn_validBlack'
//NEXT TO THE IMPORTANT PART -> I insert a link who normally have to go in my router.get but go on 'localhost:3000/forgot_password' instead of 'localhost:3001/forgot_password'
validMessage = <Link to="/change_password">{this.state.validMessage}</Link>
//END OF THE NEXT IMPORTANT PART
}
else
validMessageColor = 'SignIn_validBlue'
return (
<Router>
<div id='SignIn'>
<form action='test.html' method='POST' id='SignIn_form' onSubmit={this.submitForm}>
<div id='SignIn_emptyInput'></div>
<input type="text" placeholder="Username" name='username' value={this.state.valueUsername} onChange={this.changeUsername} />
<input type="password" placeholder="Password" name='password' value={this.state.valuePassword} onChange={this.changePassword} />
<input id='submit' type="submit" value="SIGN IN" />
</form>
<div id='SignIn_validAndSentence'><span id='SignUp_signSentence' onClick={this.props.changeForSignUp}>Not member yet ? <span id='SignIn_signWord'>SIGN UP</span></span>
<div id='SignIn_validLog' className={validLogColor}>{this.state.validLog}</div>
//THIS IS THE IMPORTANT PART
<div id='SignIn_validMessage' className={validMessageColor}>{validMessage}</div>
// END OF THE IMPORTANT PART
</div>
</div>
</Router>
);
}
}
export default SignIn;
And that works with my signup part :
import React, { Component } from 'react';
import './SignUp.css';
class SignUp extends React.Component {
constructor(props) {
super(props);
this.state = {
valueMail: '',
valuePassword: '',
valueUsername: '',
validMail: 'false',
validPassword: 'unsafe',
validUsername: 'true',
users: []
};
this.changeMail = this.changeMail.bind(this);
this.changePassword = this.changePassword.bind(this);
this.changeUsername = this.changeUsername.bind(this);
this.submitForm = this.submitForm.bind(this);
this.checkValid = this.checkValid.bind(this);
}
async componentDidMount() {
const response = await fetch('/users')
const users = await response.json()
this.setState({users: users})
}
changeMail(event) {
this.setState({valueMail: event.target.value});
this.checkValid('mail', event.target.value);
}
changePassword(event) {
this.setState({valuePassword: event.target.value});
this.checkValid('password', event.target.value);
}
changeUsername(event) {
this.setState({valueUsername: event.target.value});
this.checkValid('username', event.target.value);
}
submitForm(event) {
if (!this.state.valueMail || this.state.validMail === false || this.state.validMail === 'taken'
|| !this.state.valuePassword || this.state.validPassword === 'tooLong' || this.state.validPassword === 'unsafe'
|| !this.state.valueUsername || this.state.validUsername === false || this.state.validUsername === 'taken')
event.preventDefault();
if (!this.state.valueMail || this.state.validMail === false || this.state.validMail === 'taken')
this.setState({valueMail: ''})
if (!this.state.valuePassword || this.state.validPassword === 'tooLong' || this.state.validPassword === 'unsafe')
this.setState({valuePassword: ''});
if (!this.state.valueUsername || this.state.validUsername === false || this.state.validUsername === 'taken')
this.setState({valueUsername: ''});
}
checkValid(elem, value) {
if (elem == 'mail' && value) {
let checkMail = new RegExp(/^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
if (value.length > 30)
this.setState({validMail: 'tooLong'});
else if (checkMail.test(value))
this.setState({validMail: true});
else
this.setState({validMail: false});
}
else if (elem == 'password' && value) {
let checkPasswordWeak = new RegExp(/.{4,}/);
let checkPasswordSecure = new RegExp(/^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,}$|^.{12,}$/);
if (value.length > 30)
this.setState({validPassword: 'tooLong'});
else if (checkPasswordSecure.test(value))
this.setState({validPassword: 'secure'});
else if (checkPasswordWeak.test(value))
this.setState({validPassword: 'weak'});
else
this.setState({validPassword: 'unsafe'});
}
else if (elem == 'username' && value) {
let checkUsernameCaracters = new RegExp(/^[^\s!##$&*.><?`~%^()+=ยง"'|\\\/]+$/);
if (value.length > 30)
this.setState({validUsername: 'tooLong'});
else if (!checkUsernameCaracters.test(value))
this.setState({validUsername: false});
else
this.setState({validUsername: true});
}
if (elem == 'mail' || elem == 'username') {
let users = this.state.users;
users.forEach((user) => {
if (user[elem].toUpperCase() === value.toUpperCase()) {
if (elem == 'mail')
this.setState({validMail: 'taken'});
else if (elem == 'username')
this.setState({validUsername: 'taken'});
return;
}
});
}
}
render() {
let validMail;
let validMailColor;
let checked = '\u2713';
let wrong = '\u2717';
if (this.state.valueMail && this.state.validMail === true) {
validMail = 'Valid mail ' + checked;
validMailColor = 'SignUp_validGreen';
}
else if (this.state.valueMail && this.state.validMail === 'taken') {
validMail = 'Mail already used ' + wrong;
validMailColor = 'SignUp_validRed';
}
else if (this.state.valueMail && (this.state.validMail === 'tooLong' || this.state.validMail === false)) {
validMail = 'Mail incorect ' + wrong;
validMailColor = 'SignUp_validRed';
}
else {
validMail = '_';
validMailColor = 'SignUp_validNone';
}
let validPassword;
let validPasswordColor;
if (this.state.valuePassword && this.state.validPassword === 'tooLong') {
validPassword = 'Password too long ' + wrong;
validPasswordColor = 'SignUp_validRed';
}
else if (this.state.valuePassword && this.state.validPassword === 'unsafe') {
validPassword = 'Unsafe password ' + wrong;
validPasswordColor = 'SignUp_validRed';
}
else if (this.state.valuePassword && this.state.validPassword === 'weak') {
validPassword = 'Password weak ~';
validPasswordColor = 'SignUp_validOrange';
}
else if (this.state.valuePassword && this.state.validPassword === 'secure') {
validPassword = 'Secure password ' + checked;
validPasswordColor = 'SignUp_validGreen';
}
else {
validPassword = '_';
validPasswordColor = 'SignUp_validNone';
}
let validUsername;
let validUsernameColor;
if (this.state.valueUsername && this.state.validUsername === true) {
validUsername = 'Valid Username ' + checked;
validUsernameColor = 'SignUp_validGreen';
}
else if (this.state.valueUsername && this.state.validUsername === 'taken') {
validUsername = 'Username already used ' + wrong;
validUsernameColor = 'SignUp_validRed';
}
else if (this.state.valueUsername && this.state.validUsername === 'tooLong' || this.state.valueUsername && this.state.validUsername === false) {
validUsername = 'Username incorect ' + wrong;
validUsernameColor = 'SignUp_validRed';
}
else {
validUsername = '_';
validUsernameColor = 'SignUp_validNone';
}
return (
<div id='SignUp'>
//HERE IS THE FORM THAT REDIRECT ME WELL IN 'localhost:3001/check_signUp'
<form action='/check_signUp' method='POST' id='SignUp_form' onSubmit={this.submitForm}>
<input type="text" placeholder="Mail" name='mail' value={this.state.valueMail} onChange={this.changeMail} />
<input type="password" placeholder="Password" name='password' value={this.state.valuePassword} onChange={this.changePassword} />
<input type="text" placeholder="Username" name='username' value={this.state.valueUsername} onChange={this.changeUsername} />
<input id='submit' type="submit" value="SIGN UP" />
</form>
//END OF THE FORM
<div id='SignUp_validAndSentence'><span id='SignUp_signSentence' onClick={this.props.changeForSignIn}> Already member ? <span id='SignUp_signWord'>SIGN IN</span></span>
<div id='SignUp_validMail' className={validMailColor}>{validMail}</div>
<div id='SignUp_validPassword' className={validPasswordColor}>{validPassword}</div>
<div id='SignUp_validUsername' className={validUsernameColor}>{validUsername}</div>
</div>
</div>
);
}
}
export default SignUp;
So someone can explain me why that works with form but not with link ? Thx a lot
That works if I put :
{this.state.validMessage}
But I don't understand why I have to write all the path because I haven't to do that when I submit the form. Someone can explain me why ?
The Link component from react-router-dom is only intended to be used to navigate different routes as defined by react-router. In this case you probably just want to use a regular HTML anchor tag
{this.state.validMessage}

Resources