我已經使用具有用戶注冊的 React 構建了一個 Web 應用程式。用戶資料:
{
username: 'string',
password: 'string'
}
存在于 postgresql 資料庫中并作為狀態。我正在嘗試處理用戶嘗試使用以前使用的用戶名注冊的情況。
這是我的 ui 組件和 React 開發工具的螢屏截圖:
以下是我如何處理用戶名(如螢屏截圖所示,我將使用用戶名“bob”)已被使用的情況的摘要:
// 登錄.js
<input>組件中的“注冊”<Login/>(包含螢屏上顯示的 ui 表單的所有 .jsxuserRegister()通過onClick event. 它從我的(App.js)組件接收此功能作為道具<App/>,然后發生以下情況......// 應用程式.js
1 -
userRegister()被呼叫2- 它呼叫 2 個函式來檢查密碼和用戶名是否有效
3-如果是,它會呼叫一個函式來檢查用戶名是否已被使用,方法是檢查它是否作為記錄存在于 postgresql 資料庫中
4-它通過將當前用戶名 密碼物件作為引數發送到'/users'端點的axios請求來實作,寫在我的server.js檔案中
axios({ method: 'get', url: '/users', params: { username: 'string', password: 'string' })// 服務器.js
1- 請求由“/users”端點的快速路由處理程式接收
2- 在路由處理程式中,它
getUser()從直接與資料庫通信的 postgres.js 呼叫一個匯入函式const { getData, getUser, addUser } = require('./db/postgres.js'); app.get('/users', (req, res) => { getUser(req.query) });// postgres.js
1- 該
getUser()函式將以下查詢發送到 postgres 資料庫const getUser = (user) => { return client.query(`select * from users where username='${user.username}'`) };發送該查詢后
這個物件應該到達客戶端
response.rows: [ { id: null, username: 'bob', password: 'Pi2@' }, { id: null, username: 'bob', password: '8*lA' }, { id: null, username: 'bob', password: '8*lA' }, { id: null, username: 'bob', password: '7&lL' }, { id: null, username: 'bob', password: '*lL0' }, { id: null, username: 'bob', password: 'mM0)' }, { id: null, username: 'bob', password: '8*fF' }, { id: null, username: 'bob', password: '7&yY' }, { id: null, username: 'bob', password: '55$rR' }, { id: null, username: 'bob', password: '7&yY' }, { id: null, username: 'bob', password: '8*LAAa' }, { id: null, username: 'bob', password: '8*lAa' }, { id: null, username: 'bob', password: '8*lA' } ]這證明用戶名確實存在,實際上已經存在于資料庫中

反過來,它應該更新
alreadyRegistered state到true并呼叫警報“用戶已經存在”,但是,如頂部螢屏截圖所示,alreadyRegistered沒有及時更新它確實在幾毫秒后顯示 Rect devtools 中的更新

我相當確定問題是由于狀態掛鉤和生命周期方法是異步的,但是話雖如此,我如何在第 63 行的代碼執行之前將 alreadyRegisted 狀態更新為 true?
以下是協同作業的代碼檔案片段。讓我知道是否需要更多資訊/背景關系
- 登錄.js
import React from 'react';
import { Link } from 'react-router-dom';
import { NavBar, Footer } from'../Imports.js';
const Login = ({ userAuth, getUserAuth, userLogin, authorized, userRegister }) => {
console.log('userAuth:', userAuth);
return (
<div id='login'>
<NavBar userAuth={userAuth} getUserAuth={getUserAuth} authorized={authorized} />
<section id='login-main'>
<form>
<input type='text' placeholder='username' onChange={() => {getUserAuth({...userAuth, username: event.target.value})}}/>
<input type='text' placeholder='password'onChange={() => {getUserAuth({...userAuth, password: event.target.value})}}/>
<input type='submit' value='Login' onClick={() => {event.preventDefault(); userLogin()}}/>
<input type='submit' value='Register' onClick={() => {event.preventDefault(); userRegister();}}/>
</form>
</section>
<Footer/>
</div>
)
};
export default Login;
- 應用程式.js
import React, { useState, useEffect } from 'react';
import Router from './Router.js';
const axios = require('axios');
const App = () => {
// Login/user state
const [userAuth, getUserAuth] = useState({username: '', password: ''});
const [authorized, authorizeUser] = useState(false);
const [alreadyRegistered, userExists] = useState(false);
// new user register
const userRegister = () => { // <- 1)
if (validUsername() && validPassword()) {
checkIfExists();
console.log('alreadyRegistered:', alreadyRegistered);
if (alreadyRegistered) {
alert('user already exists');
} else {
console.log('ERROR: should update alreadyRegistered state to TRUE and invoke ALERT')
}
}
}
// check if username is already registered
const checkIfExists = () => { // <- 3)
axios({
method: 'get',
url: '/users',
params: userAuth
})
.then((res) => {
console.log(res.data.length)
if (res.data.length) {
console.log(res.data.length, 'INNER')
userExists(true);
}
})
.catch((err) => {
throw err;
})
}
};
- 服務器.js
// ----- external modules -----
require('dotenv').config();
const express = require('express');
const path = require('path');
const { getData, getUser, addUser } = require('./db/postgres.js');
// check if user exists
app.get('/users', (req, res) => {
console.log('req.body:', req.query)
getUser(req.query)
.then((response) => {
console.log('response.rows:', response.rows);
res.send(response.rows);
})
.catch((err) => {
if (err) {
throw err;
}
});
});
- postgres.js
const { Client } = require('pg');
const getUser = (user) => {
return client.query(`select * from users where username='${user.username}'`)
};
uj5u.com熱心網友回復:
在回答狀態問題之前,了解您撰寫的應用程式易受 SQL 注入攻擊很重要。postgres.js您應該使用引數化查詢,而不是檔案中的模板字串。
至于 的值alreadyRegistered,您是正確的,問題在于狀態掛鉤的異步性質。
您可以使用該useEffect函式來處理更新,alreadyRegistered如下所示:
useEffect(() => {
if (alreadyRegistered) {
alert('user already exists');
} else {
// create user...
}
}, [alreadyRegistered]);
您還可以避免alreadyRegistered在狀態中進行跟蹤,只需checkIfExists根據需要呼叫:
// first, remove alreadyRegistered state
const [userAuth, getUserAuth] = useState({username: '', password: ''});
const [authorized, authorizeUser] = useState(false);
// then redefine checkIfExists to return Promise<boolean>
const checkIfExists = async () => {
const res = await axios({
method: 'get',
url: '/users',
params: userAuth
})
return !!res.data.length; // convert fetch result to boolean
}
// then call checkIfExists in userRegister
const userRegister = async () => {
if (validUsername() && validPassword()) {
const alreadyRegistered = await checkIfExists();
if (alreadyRegistered) {
alert('user already exists');
} else {
// handle user creation
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/533677.html
標籤:反应异步反应挂钩状态
