我是React和ES6的新手,我有一个像这样的组件:
import React, { useState } from 'react';
const Order = () => {
let username='Test',password = 'secret';
const [Data,setData]=useState({title:'',submit:false});
const [List,setList]=useState({title:'',submit:false});
const Clicked = ()=>{
if(username==='Test'){
setData({title:'Yes',submit:true});
}
else{
setData({title:'No',submit:false});
}
if(password==='secret'){
setList({title:'Yes',submit:true});
}
else{
setList({title:'No',submit:false});
}
console.log(Data.submit,List.submit);
if(Data.submit && List.submit){
alert('Time to Submit')
}
}
return (
<div>
<button onClick={Clicked}>Click</button>
</div>
);
}
export default Order;
我的问题是,当我单击Button时,Data.submit
和List.submit
在第一次单击时都被认为是False,但是在第二次单击时它们都变为true,并且会警告alert('Time to Submit')
。
因为我将数据和列表用于两个不同的按钮,所以不能使用useEffect()
。
我不希望用户单击两次。我该如何处理?
答案 0 :(得分:2)
这主要是因为设置状态是异步的,因此,如果您像同步代码那样调用,它将无法按预期工作。
要解决此问题,您可以执行以下操作:
import React, { useState } from 'react';
const Order = () => {
let username='Test',password = 'secret';
const [Data,setData]=useState({title:'',submit:false});
const [List,setList]=useState({title:'',submit:false});
const Clicked = ()=>{
const data = {title: '', submit: false};
const list = {title: '', submit: false};
if(username==='Test'){
data.title = 'Yes';
data.submit = true;
}
else{
data.title = 'No';
data.submit = false;
}
if(password==='secret'){
list.title = 'Yes';
list.submit = true;
}
else{
list.title = 'No';
list.submit = false;
}
console.log(Data.submit,List.submit);
if(data.submit && list.submit){
alert('Time to Submit')
}
setData(data);
setList(list);
}
return (
<div>
<button onClick={Clicked}>Click</button>
</div>
);
}
export default Order;
答案 1 :(得分:1)
const Order = () => {
let username = "Test",
password = "secret";
const [Data, setData] = useState({ title: "", submit: false });
const [List, setList] = useState({ title: "", submit: false });
const Clicked = () => {
let dataSubmit, listSubmit;
if (username === "Test") {
dataSubmit = true;
setData({ title: "Yes", submit: true });
} else {
setData({ title: "No", submit: false });
}
if (password === "secret") {
listSubmit = true;
setList({ title: "Yes", submit: true });
} else {
setList({ title: "No", submit: false });
}
if (dataSubmit && listSubmit) {
alert("Time to Submit");
}
};
return (
<div>
<button onClick={Clicked}>Click</button>
</div>
);
};
答案 2 :(得分:1)
setState是异步的(React将决定何时应用更改以提高性能),在您登录控制台时,状态尚未更改。如果您不想使用useEffect
来检测状态何时更改,可以使用函数中已有的变量
const Clicked = ()=>{
if(username==='Test'){
setData({title:'Yes',submit:true});
}
else{
setData({title:'No',submit:false});
}
if(password==='secret'){
setList({title:'Yes',submit:true});
}
else{
setList({title:'No',submit:false});
}
if(username==='Test' && password==='secret'){
alert('Time to Submit')
}
}
答案 3 :(得分:0)
useState
回调与我的直觉是异步的,这就是为什么日志记录输出数据的不变版本的原因。 @Nishant的上述解决方案应该可以正常工作。
答案 4 :(得分:0)
这是我想出的解决方案,我添加了一些评论以使其更加清楚,如果您有任何疑问,请随时向我提问。 (请注意,我不是母语人士,由于我的英语不好意思)
import React, { useState, useEffect } from 'react';
const Order = () => {
let username='Test',password = 'secret';
//fist of all, I recomend you to call your useState variables
//always using lowercase becase if you name it uppercase
//it means that is a component o a class
const [data, setData]=useState({title:'',submit:false});
const [list, setList]=useState({title:'', submit:false});
//I also recomment to call you functions using camelCase using the first letter with lowercase
const clicked = ()=>{
// I created a couple variables to improve readability and help with logic
const correctUsername = username === 'Test' //this will return true if username equal test, otherwise will return false;
const correctPassword = password === 'secret'; //same here
//Here, you can use a ternary, that is the same as is else, but in a short way
// see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator
setData(correctUsername ? {title: 'Yes', submit: true} : {title: 'No', submit: false});
setList(correctPassword ? {title: 'Yes', submit: true} : {title: 'No', submit: false});
}
//You can use an useEffect to watch stateChanges
useEffect(()=>{
if(data.submit && list.submit){
console.log({data, list})
alert('Time to Submit')
}
},[data, list])
return (
<div>
<button onClick={clicked}>Click</button>
</div>
);
}
export default Order;