在同一事件处理程序中更新多个 React 状态
Updating Multiple React State within the same event handler
这些是我使用钩子的状态:
const [adminProfile, setProfile] = useState({
locations: [],
});
const [location, setLocation] = useState({
locationName: "",
location: {},
locationPhone: "",
locationEmail: "",
staff: [],
multipleKitchens: false,
kitchens: [],
});
const [locationList, setLocationList] = useState([]);
const [locationAddress, setAddress] = useState({
streetAddress: "",
streetAddress2: "",
city: "",
state: "",
zip: "",
country: "USA"
});
我有一堆带有 onChange 处理程序的字段和一个需要按顺序更新 3 个状态的 onClick 处理程序。首先,LocationAddress 必须成为位置状态中位置 属性 的状态。其次,必须使用唯一 ID 更新位置状态,然后将该唯一 ID 插入到 locationList 状态的数组中。最后,locationList 状态的整个数组被添加到 adminProfile 状态的位置 属性。这些都在一个组件中。
const handleClickLocation = () => {
setLocation(prevValue => ({
...prevValue,
locationID: uuidv4(),
location: locationAddress
}));
setLocationList(prevValue => [...prevValue, location.locationID]);
setProfile(prevValue => ({
...prevValue,
locations: locationList
}))
第一次触发点击处理程序时,它只在处理程序中设置第一个状态,并将“未定义”发送到第二个状态。当单击处理程序被第二次单击时,它会正常运行。我希望所有状态同时更新。我试过 forceUpdate(),但无法弄清楚语法。我试过使用 ReactDOM.unstable_batchedUpdates 但它仍然表现相同。
我怎样才能让它工作?我想将其保留在一个组件中。这可能吗?
这是使用 useEffect 挂钩更新的完整代码:
import React, {useState, useEffect} from "react";
import axios from "axios";
const { v4: uuidv4 } = require('uuid');
const CompanyProfileInfo = (props) => {
const todayDate = () => {
let today = new Date();
let day = today.getDate();
let month = today.getMonth() + 1;
let year = today.getFullYear();
if (day < 10) day = '0' + day;
if(month < 10) month = '0' + month;
return (month + "/" + day + "/" + year);
}
const [adminProfile, setProfile] = useState({
companyID: props.companyInfo.companyID,
firstName: "",
lastName: "",
phonePrimary: "",
phoneSecondary: "",
emailSecondary: "",
streetAddress: "",
streetAddress2: "",
city: "",
state: "",
zip: "",
country: "USA",
multipleLocations: false,
locations: [],
membershipLevel: "Basic",
joinedDate: todayDate(),
});
const [location, setLocation] = useState({
locationName: "",
locationPhone: "",
locationEmail: "",
staff: [],
multipleKitchens: false,
kitchens: [],
});
const [locationAddress, setAddress] = useState({
streetAddress: "",
streetAddress2: "",
city: "",
state: "",
zip: "",
country: "USA"
});
const [locationList, setLocationList] = useState([]);
useEffect(() => {
setLocationList(prevValue => [...prevValue, location.locationID]);
}, [location.locationID]);
useEffect(() => {
if (locationList[0] === undefined) {
{locationList.shift()}
}
setProfile(prevValue => ({
...prevValue,
locations: locationList
})
)
}, [locationList])
const handleChange = (event) => {
const {name, value} = event.target;
setProfile(prevValue => ({
...prevValue,
[name]: value
}))
}
const handleChangeLocations = (event) => {
const {name, value} = event.target;
setLocation(prevValue => ({
...prevValue,
[name]: value
}));
};
const handleChangeLocations1 = (event) => {
const {name, value} = event.target;
setAddress(prevValue => ({
...prevValue,
[name]: value
}));
};
const handleClickLocation = () => {
setLocation(prevValue => ({
...prevValue,
locationID: uuidv4(),
location: locationAddress,
}));
};
const handleClick = () => {
axios.post('http://localhost:3001/profileinfo', adminProfile)
.then(res => {
props.supportFunctions.setUpLocations(res);
})
.catch(function (error) {
console.log(error);
})
}
return (
<div>
</div>
)
}
export default CompanyProfileInfo;
状态更新是异步行为,因此您将获得 setLocationList 未定义的 locationID。
在 class 组件中,我们可以像这样使用回调来调用 setState -
this.setState({ data: newData }, () => { console.log("This will get printed after setState") })
但是在你的情况下,你使用的是函数组件,所以你必须使用 useEffect react hook 来监听你的数据变化,然后更新状态中的其他数据。
看看这个问题 -
setState是asynchronous
,意思是当它被调用时,它的状态不会同时更新,它需要一些时间来执行它的动作.
您可以使用 useEffect
来做到这一点。
useEffect
将仅在指定状态(括号内)更改
时执行操作
useEffect(() => {
setLocation({
...location,
location: locationAddress,
locationID: uuidv4()
})
}, [locationAddress]) //When locationAddress changes, setLocation
useEffect(() => {
setLocationList([
...locationList,
location.locationID
])
}, [location]) //When location changes, insert Id
Ps:您的代码中可以有多个 useEffects。
这些是我使用钩子的状态:
const [adminProfile, setProfile] = useState({
locations: [],
});
const [location, setLocation] = useState({
locationName: "",
location: {},
locationPhone: "",
locationEmail: "",
staff: [],
multipleKitchens: false,
kitchens: [],
});
const [locationList, setLocationList] = useState([]);
const [locationAddress, setAddress] = useState({
streetAddress: "",
streetAddress2: "",
city: "",
state: "",
zip: "",
country: "USA"
});
我有一堆带有 onChange 处理程序的字段和一个需要按顺序更新 3 个状态的 onClick 处理程序。首先,LocationAddress 必须成为位置状态中位置 属性 的状态。其次,必须使用唯一 ID 更新位置状态,然后将该唯一 ID 插入到 locationList 状态的数组中。最后,locationList 状态的整个数组被添加到 adminProfile 状态的位置 属性。这些都在一个组件中。
const handleClickLocation = () => {
setLocation(prevValue => ({
...prevValue,
locationID: uuidv4(),
location: locationAddress
}));
setLocationList(prevValue => [...prevValue, location.locationID]);
setProfile(prevValue => ({
...prevValue,
locations: locationList
}))
第一次触发点击处理程序时,它只在处理程序中设置第一个状态,并将“未定义”发送到第二个状态。当单击处理程序被第二次单击时,它会正常运行。我希望所有状态同时更新。我试过 forceUpdate(),但无法弄清楚语法。我试过使用 ReactDOM.unstable_batchedUpdates 但它仍然表现相同。
我怎样才能让它工作?我想将其保留在一个组件中。这可能吗?
这是使用 useEffect 挂钩更新的完整代码:
import React, {useState, useEffect} from "react";
import axios from "axios";
const { v4: uuidv4 } = require('uuid');
const CompanyProfileInfo = (props) => {
const todayDate = () => {
let today = new Date();
let day = today.getDate();
let month = today.getMonth() + 1;
let year = today.getFullYear();
if (day < 10) day = '0' + day;
if(month < 10) month = '0' + month;
return (month + "/" + day + "/" + year);
}
const [adminProfile, setProfile] = useState({
companyID: props.companyInfo.companyID,
firstName: "",
lastName: "",
phonePrimary: "",
phoneSecondary: "",
emailSecondary: "",
streetAddress: "",
streetAddress2: "",
city: "",
state: "",
zip: "",
country: "USA",
multipleLocations: false,
locations: [],
membershipLevel: "Basic",
joinedDate: todayDate(),
});
const [location, setLocation] = useState({
locationName: "",
locationPhone: "",
locationEmail: "",
staff: [],
multipleKitchens: false,
kitchens: [],
});
const [locationAddress, setAddress] = useState({
streetAddress: "",
streetAddress2: "",
city: "",
state: "",
zip: "",
country: "USA"
});
const [locationList, setLocationList] = useState([]);
useEffect(() => {
setLocationList(prevValue => [...prevValue, location.locationID]);
}, [location.locationID]);
useEffect(() => {
if (locationList[0] === undefined) {
{locationList.shift()}
}
setProfile(prevValue => ({
...prevValue,
locations: locationList
})
)
}, [locationList])
const handleChange = (event) => {
const {name, value} = event.target;
setProfile(prevValue => ({
...prevValue,
[name]: value
}))
}
const handleChangeLocations = (event) => {
const {name, value} = event.target;
setLocation(prevValue => ({
...prevValue,
[name]: value
}));
};
const handleChangeLocations1 = (event) => {
const {name, value} = event.target;
setAddress(prevValue => ({
...prevValue,
[name]: value
}));
};
const handleClickLocation = () => {
setLocation(prevValue => ({
...prevValue,
locationID: uuidv4(),
location: locationAddress,
}));
};
const handleClick = () => {
axios.post('http://localhost:3001/profileinfo', adminProfile)
.then(res => {
props.supportFunctions.setUpLocations(res);
})
.catch(function (error) {
console.log(error);
})
}
return (
<div>
</div>
)
}
export default CompanyProfileInfo;
状态更新是异步行为,因此您将获得 setLocationList 未定义的 locationID。 在 class 组件中,我们可以像这样使用回调来调用 setState -
this.setState({ data: newData }, () => { console.log("This will get printed after setState") })
但是在你的情况下,你使用的是函数组件,所以你必须使用 useEffect react hook 来监听你的数据变化,然后更新状态中的其他数据。
看看这个问题 -
setState是asynchronous
,意思是当它被调用时,它的状态不会同时更新,它需要一些时间来执行它的动作.
您可以使用 useEffect
来做到这一点。
useEffect
将仅在指定状态(括号内)更改
useEffect(() => {
setLocation({
...location,
location: locationAddress,
locationID: uuidv4()
})
}, [locationAddress]) //When locationAddress changes, setLocation
useEffect(() => {
setLocationList([
...locationList,
location.locationID
])
}, [location]) //When location changes, insert Id
Ps:您的代码中可以有多个 useEffects。