Javascript 对象数组在React中未完全渲染,并在控制台上显示与实际不匹配的数组长度
我在React中渲染对象阵列时遇到问题。出于某种原因,在它拥有的5个元素中,它只渲染了3个。我已经在控制台中进行了检查,如下所示: 出于某种原因,最初在控制台上显示该数组有3个元素,但如果我在控制台中检查它,则有5个元素而不是3个。渲染的元素正好是前3个元素。这是React组件,以防有帮助:Javascript 对象数组在React中未完全渲染,并在控制台上显示与实际不匹配的数组长度,javascript,reactjs,object,Javascript,Reactjs,Object,我在React中渲染对象阵列时遇到问题。出于某种原因,在它拥有的5个元素中,它只渲染了3个。我已经在控制台中进行了检查,如下所示: 出于某种原因,最初在控制台上显示该数组有3个元素,但如果我在控制台中检查它,则有5个元素而不是3个。渲染的元素正好是前3个元素。这是React组件,以防有帮助: import React, { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import '
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import './RegisterBlock.css';
const RegisterBlock = () => {
const [gamertag, setGamerTag] = useState("");
const [password, setPassword] = useState("");
const [repassword, setRepassword] = useState("");
const [mail, setMail] = useState("");
const [isChecked, setIsChecked] = useState(false);
const [errors, setErrors] = useState(null);
const handleChange = (event) => {
event.target.name === "password" ? setPassword(event.target.value) :
event.target.name === "repassword" ? setRepassword(event.target.value) :
event.target.name === "gamertag" ? setGamerTag(event.target.value) :
event.target.name === "email" ? setMail(event.target.value) : setIsChecked(!isChecked) ;
}
const handleSubmit = (event) => {
event.preventDefault();
var totalErrors = [];
if (gamertag.length === 0 || gamertag.length > 30) {
totalErrors.push({"error": "La contraseña debe tener entre 2 y 30 caracteres"});
}
if (!/^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[A-Za-z]+$/.test(mail)) {
totalErrors.push({"error": "Introduce un correo válido"});
}
if (!isChecked) {
totalErrors.push({"error": "Debes aceptar haber leído las políticas para poder registrarte"});
}
const url = "URL API" + mail;
fetch(url)
.then(response => response.json())
.then(data => {
data.length > 0 && totalErrors.push({"error": "Ya hay una cuenta con este correo"});
});
const urlGamertag = "URL API" + gamertag;
fetch(urlGamertag)
.then(response => response.json())
.then(data => {
data.length > 0 && totalErrors.push({"error": "El gamertag ya ha sido usado por otro usuario"});
});
setErrors(totalErrors);
}
useEffect(() => {
if (errors?.length === 0) {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: gamertag,
password: password,
email: mail
})
};
fetch('URL API', requestOptions)
.then(response => response.json())
}
}, [errors?.length === 0])
return (
<div className="login-block">
<div className="wrapper">
<form onSubmit={handleSubmit} method="post">
<input type="text" placeholder="Gamertag" name="gamertag" value={gamertag} onChange={handleChange}/>
<input type="mail" placeholder="Email" name="email" value={mail} onChange={handleChange}/>
<input type="password" placeholder="Contraseña" name="password" value={password} onChange={handleChange}/>
<input type="password" placeholder="Verifica contraseña" name="repassword" value={repassword} onChange={handleChange}/>
<div className="form__checkbox">
<input onChange={handleChange} name="policy" id="policy" type="checkbox" checked={isChecked} />
<label htmlFor="policy">Al registrarte confirmas haber leído la <Link to="/politica-de-privacidad">Política de privacidad</Link> y Aviso legal.</label>
</div>
{console.log(errors)}
{
errors?.length > 0 && (
<ul className="form--errors">
{
errors.map((item, index) => {
return <li key={index}>{item.error}</li>
})
}
</ul>
)
}
<input type="submit" value="Registrarse"/>
</form>
</div>
</div>
)
}
export default RegisterBlock;
import React,{useffect,useState}来自“React”;
从'react router dom'导入{Link};
导入“./RegisterBlock.css”;
常量寄存器块=()=>{
const[gamertag,setGamerTag]=useState(“”);
const[password,setPassword]=useState(“”);
const[repassword,setRepassword]=useState(“”);
const[mail,setMail]=useState(“”);
const[isChecked,setIsChecked]=useState(false);
const[errors,setErrors]=useState(null);
常量handleChange=(事件)=>{
event.target.name==“密码”?设置密码(event.target.value):
event.target.name==“repassword”?设置repassword(event.target.value):
event.target.name==“gamertag”?setGamerTag(event.target.value):
event.target.name==“email”?setMail(event.target.value):setIsChecked(!isChecked);
}
const handleSubmit=(事件)=>{
event.preventDefault();
var totalErrors=[];
如果(gamertag.length==0 | | gamertag.length>30){
totalErrors.push({“error”:“La contraseña debe tener entre 2 y 30克拉”});
}
如果(!/^[a-zA-Z0-9]+@[a-zA-Z0-9]+\[a-zA-z]+$/.测试(邮件)){
推送({“错误”:“引入联合国科雷奥·瓦利多”});
}
如果(!已检查){
推送({“error”:“Debes aceptar haber leído las políticas para poder registerte”});
}
const url=“url API”+邮件;
获取(url)
.then(response=>response.json())
。然后(数据=>{
data.length>0&&totalErrors.push({“error”:“Ya hay una cuenta con este correo”});
});
const urlGamertag=“URL API”+gamertag;
获取(urlGamertag)
.then(response=>response.json())
。然后(数据=>{
data.length>0&&totalErrors.push({“error”:“El gamertag ya ha sido usado por otro usuario”});
});
设置错误(总错误);
}
useffect(()=>{
如果(错误?.length==0){
常量请求选项={
方法:“POST”,
标题:{'Content-Type':'application/json'},
正文:JSON.stringify({
姓名:gamertag,,
密码:密码,
电邮:电邮
})
};
获取('URL API',请求选项)
.then(response=>response.json())
}
},[errors?.length==0])
返回(
Al Registrate confirmas haber leído la Política de privacidad y Aviso leído la Política de privacidad y leído la Aviso legal。
{console.log(错误)}
{
错误?长度>0&&(
{
错误。映射((项目,索引)=>{
返回- {item.error}
})
}
)
}
)
}
导出默认注册表锁;
前3次验证是同步的,因此它们会立即添加到数组中并呈现。然而,最后2个是在服务器端验证的,这需要一些时间。当响应到达时,渲染过程完成。虽然错误已添加到数组中,但对数组本身的引用保持不变,因此React不会接受更改。因此这里有两个选项:要么使用克隆数组对每个响应执行setErrors
,要么等待所有验证完成,然后再呈现任何内容。第一个将导致刷新,因此在这种情况下,最好等待fetch
。请注意,您有两个请求,它们可能可以同时发出,因此将它们包装成Promise.all
。顺序选项(一次一个验证):
同时触发两个请求:
const firstPromise = fetch(url)
...
const secondPromise =fetch(urlGamertag)
...
await Promise.all([firstPromice , secondPromise ])
setErrors(totalErrors);
您没有等待响应,因此当它们到达时,组件被渲染,它们只是被推到同一个数组中而没有反应。添加
wait
在fetch
@NadiaChibrikova哇,就是这样!非常感谢你!您能否将解决方案添加为答案,以便我验证它?完成(还添加了您可能希望使用的其他内容:)
const firstPromise = fetch(url)
...
const secondPromise =fetch(urlGamertag)
...
await Promise.all([firstPromice , secondPromise ])
setErrors(totalErrors);